在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应。  同时我们又需要在工作线程中更新UI界面上的控件,

下面介绍几种常用的方法

阅读目录

  1. 线程间操作无效
  2. 第一种办法:禁止编译器对跨线程访问做检查
  3. 第二种办法: 使用delegate和invoke来从其他线程中调用控件
  4. 第三种办法: 使用delegate和BeginInvoke来从其他线程中控制控件
  5. 第四种办法: 使用BackgroundWorker组件
  6. 源代码下载

线程间操作无效

界面上有一个button和一个label,  点击button会启动一个线程来更新Label的值

        private void button1_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel));
thread1.Start("更新Label");
} private void UpdateLabel(object str)
{
this.label1.Text = str.ToString();
}

运行后, 程序会报错 "跨线程操作无效,从不是创建"label1"的线程访问它"

这是因为.NET禁止了跨线程调用控件, 否则谁都可以操作控件,最后可能造成错误。

下面介绍几种跨线程调用控件的方法

第一种办法:禁止编译器对跨线程访问做检查

这是最简单的办法, 相当于不检查线程之间的冲突,允许各个线程随便乱搞,最后Lable1控件的值是什么就难以预料了 (不推荐使用这种方法)

        public Form1()
{
InitializeComponent();
// 加入这行
Control.CheckForIllegalCrossThreadCalls = false;
}

第二种办法: 使用delegate和invoke来从其他线程中调用控件

调用控件的invoke方法,就可以控制控件了,例如

        private void button2_Click(object sender, EventArgs e)
{
Thread thread1 = new Thread(new ParameterizedThreadStart(UpdateLabel2));
thread1.Start("更新Label");
} private void UpdateLabel2(object str)
{
if (label2.InvokeRequired)
{
// 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它
Action<string> actionDelegate = (x) => { this.label2.Text = x.ToString(); };
// 或者
// Action<string> actionDelegate = delegate(string txt) { this.label2.Text = txt; };
this.label2.Invoke(actionDelegate, str);
}
else
{
this.label2.Text = str.ToString();
}
}

第三种办法: 使用delegate和BeginInvoke来从其他线程中控制控件

只要把上面的 this.label2.Invoke(actionDelegate, str); 中的 Invoke 改为BeginInvoke方法就可以了

Invoke方法和BeginInvoke方法的区别是

Invoke方法是同步的, 它会等待工作线程完成,

BeginInvoke方法是异步的, 它会另起一个线程去完成工作线程

第四种办法: 使用BackgroundWorker组件(推荐使用这个方法)

BackgroundWorker是.NET里面用来执行多线程任务的控件,它允许编程者在一个单独的线程上执行一些操作。耗时的操作(如下载和数据库事务)。用法简单

        private void button4_Click(object sender, EventArgs e)
{
using (BackgroundWorker bw = new BackgroundWorker())
{
bw.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_RunWorkerCompleted);
bw.DoWork += new DoWorkEventHandler(bw_DoWork);
bw.RunWorkerAsync("Tank");
}
} void bw_DoWork(object sender, DoWorkEventArgs e)
{
// 这里是后台线程, 是在另一个线程上完成的
// 这里是真正做事的工作线程
// 可以在这里做一些费时的,复杂的操作
Thread.Sleep();
e.Result = e.Argument + "工作线程完成";
} void bw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了
this.label4.Text = e.Result.ToString();
}

源代码下载

请用VS2010打开【下载】

 

C# 跨线程调用控件的更多相关文章

  1. 【转载】C# 跨线程调用控件

    转自:http://www.cnblogs.com/TankXiao/p/3348292.html 感谢原作者,转载以备后用 在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停 ...

  2. C# 跨线程调用控件的4中方法

    原文:C# 跨线程调用控件 在C# 的应用程序开发中, 我们经常要把UI线程和工作线程分开,防止界面停止响应.  同时我们又需要在工作线程中更新UI界面上的控件, 下面介绍几种常用的方法 阅读目录 线 ...

  3. 跨线程调用控件之MethodInvoker

    原文:http://www.cnblogs.com/cm8448940/archive/2008/07/10/1240045.html 使用到两个控件,一个按钮button1,一个标签label1. ...

  4. WinForm与WPF下跨线程调用控件

    Winform下: public delegate void UpadataTextCallBack(string str,TextBox text); public void UpadtaText( ...

  5. winform 跨线程 调用控件

    public delegate void rtbCallBack(string txt); public void rtbAddText(string txt) { if (this.rtb.Invo ...

  6. C#跨线程操作控件的最简单实现探究

    随着程序复杂度的提高,程序不可避免会出现多个线程,此时就很可能存在跨线程操作控件的问题. 跨线程操作UI控件主要有三类方式: 1.禁止系统的线程间操作检查.(此法不建议使用) 2.使用Invoke(同 ...

  7. C# 关于跨线程访问控件问题

    跨线程访问控件问题的原因是:控件都是在主线程中创建的,而系统默认控件的修改权归其创建线程所有.在子线程中如果需要直接修改控件的内容,需要使用委托机制将控件的修改操作交给主线程处理.因此,当没有使用委托 ...

  8. 在.Net中进行跨线程的控件操作(下篇:BackgroundWorker)

    在.Net中,如果我们在非UI线程上访问窗体上的控件的时候,会产生一个跨线程调用的异常,那么如何处理这种情况呢?在上一章中,我介绍了使用Control.Invoke方法,如果你不习惯使用委托,那么.N ...

  9. c# winform InvokeRequired 解决跨线程访问控件

    C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它. Windows 窗体中 ...

随机推荐

  1. Handle源码分析,深入群内了解风骚的Handle机制

    Hanlder的使用方式一: private static Handler mHandler = new Handler(){ public void handleMessage(android.os ...

  2. Linux下执行的java命令重定向到文件中的方法

    在Linux下通常会执行如:java -version 的命令, 但是,命令只是打印到了屏幕上不能重定向到文件中或标准输出流中. 此时需要将错误输出流重定向到标准输出流中就可以得到了. 比如:java ...

  3. 关于qt的集成开发环境

    事情是这样的,在archlinux中安装好qt5之后,只发现了一个 qt designer,这个只能用来写界面.其它的几个程序(qt assistant)算是查文档的这类辅助的程序. 记得在windo ...

  4. MVC4 Filter 验证客户端访问类型(移动端、PC端)

    Filter: 1 /// <summary> /// 检测是否是手机访问 /// </summary> public class IsMobileFilter : Actio ...

  5. python实现指定目录下JAVA文件单词计数的多进程版本

    要说明的是, 串行版本足够快了, 在我的酷睿双核 debian7.6 下运行只要 0.2s , 简直是难以超越. 多进程版本难以避免大量的进程创建和数据同步与传输开销, 性能反而不如串行版本, 只能作 ...

  6. LINK : fatal error LNK1104: 无法打开文件“LIBCD.lib”

    出现这类问题一般是由于所运行的项目是VC6(或者vs2003)创建的,而后又用VS2005或者更高版本工具打开项目导致的,原因都是因为LIBCD.lib文件被更改了.要解决问题的话,只要在链接设置那里 ...

  7. SelectMany等LINQ运算符的使用

    public class Racer : IComparable<Racer>, IFormattable { public string FirstName { get; set; } ...

  8. MySQL Workbench 6 不能删除数据等问题(“Error Code: 1175”) 和入门教程

    网络资料收集 当用MySQL Workbench进行数据库的批量更新时,执行一个语句会碰到以下错误提示: Error Code: 1175 You are using safe...without a ...

  9. 数据库事务的特性(ACID)

    数据库的事务是数据库中一系列(增删查改)操作的集合. 一般来说,事务的范围根据业务而定,比如转账.修改个人信息 转账:从A账户将200元转移到B账户 从A账户中扣除200元 将200元加入到B账户中 ...

  10. 深度优先搜索(DFS)

    定义: (维基百科:https://en.wikipedia.org/wiki/Depth-first_search) 深度优先搜索算法(Depth-First-Search),是搜索算法的一种.是沿 ...