原文:C# 跨线程调用控件

在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");
}
    </span><span style="color:rgb(0,0,255); line-height:1.5!important">private</span> <span style="color:rgb(0,0,255); line-height:1.5!important">void</span> UpdateLabel(<span style="color:rgb(0,0,255); line-height:1.5!important">object</span><span style="line-height:1.5!important"> str)
{
</span><span style="color:rgb(0,0,255); line-height:1.5!important">this</span>.label1.Text =<span style="line-height:1.5!important"> str.ToString();
}</span></pre>

运行后, 程序会报错 "跨线程操作无效,从不是创建"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");
}
    </span><span style="color:rgb(0,0,255); line-height:1.5!important">private</span> <span style="color:rgb(0,0,255); line-height:1.5!important">void</span> UpdateLabel2(<span style="color:rgb(0,0,255); line-height:1.5!important">object</span><span style="line-height:1.5!important"> str)
{
</span><span style="color:rgb(0,0,255); line-height:1.5!important">if</span><span style="line-height:1.5!important"> (label2.InvokeRequired)
{
</span><span style="color:rgb(0,128,0); line-height:1.5!important">//</span><span style="color:rgb(0,128,0); line-height:1.5!important"> 当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它</span>
Action&lt;<span style="color:rgb(0,0,255); line-height:1.5!important">string</span>&gt; actionDelegate = (x) =&gt; { <span style="color:rgb(0,0,255); line-height:1.5!important">this</span>.label2.Text =<span style="line-height:1.5!important"> x.ToString(); };
</span><span style="color:rgb(0,128,0); line-height:1.5!important">//</span><span style="color:rgb(0,128,0); line-height:1.5!important"> 或者
</span><span style="color:rgb(0,128,0); line-height:1.5!important">//</span><span style="color:rgb(0,128,0); line-height:1.5!important"> Action&lt;string&gt; actionDelegate = delegate(string txt) { this.label2.Text = txt; };</span>
<span style="color:rgb(0,0,255); line-height:1.5!important">this</span><span style="line-height:1.5!important">.label2.Invoke(actionDelegate, str);
}
</span><span style="color:rgb(0,0,255); line-height:1.5!important">else</span><span style="line-height:1.5!important">
{
</span><span style="color:rgb(0,0,255); line-height:1.5!important">this</span>.label2.Text =<span style="line-height:1.5!important"> str.ToString();
}
}</span></pre>

第三种办法: 使用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");
}
}
    </span><span style="color:rgb(0,0,255); line-height:1.5!important">void</span> bw_DoWork(<span style="color:rgb(0,0,255); line-height:1.5!important">object</span><span style="line-height:1.5!important"> sender, DoWorkEventArgs e)
{
</span><span style="color:rgb(0,128,0); line-height:1.5!important">//</span><span style="color:rgb(0,128,0); line-height:1.5!important"> 这里是后台线程, 是在另一个线程上完成的
</span><span style="color:rgb(0,128,0); line-height:1.5!important">//</span><span style="color:rgb(0,128,0); line-height:1.5!important"> 这里是真正做事的工作线程
</span><span style="color:rgb(0,128,0); line-height:1.5!important">//</span><span style="color:rgb(0,128,0); line-height:1.5!important"> 可以在这里做一些费时的,复杂的操作</span>
Thread.Sleep(<span style="color:rgb(128,0,128); line-height:1.5!important">5000</span><span style="line-height:1.5!important">);
e.Result </span>= e.Argument + <span style="color:rgb(128,0,0); line-height:1.5!important">"</span><span style="color:rgb(128,0,0); line-height:1.5!important">工作线程完成</span><span style="color:rgb(128,0,0); line-height:1.5!important">"</span><span style="line-height:1.5!important">;
} </span><span style="color:rgb(0,0,255); line-height:1.5!important">void</span> bw_RunWorkerCompleted(<span style="color:rgb(0,0,255); line-height:1.5!important">object</span><span style="line-height:1.5!important"> sender, RunWorkerCompletedEventArgs e)
{
</span><span style="color:rgb(0,128,0); line-height:1.5!important">//</span><span style="color:rgb(0,128,0); line-height:1.5!important">这时后台线程已经完成,并返回了主线程,所以可以直接使用UI控件了 </span>
<span style="color:rgb(0,0,255); line-height:1.5!important">this</span>.label4.Text =<span style="line-height:1.5!important"> e.Result.ToString();
}</span></pre>

转自https://www.cnblogs.com/lonelyxmas/p/4097737.html

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

  1. C# 跨线程调用控件

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

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

    转自:http://www.cnblogs.com/TankXiao/p/3348292.html 感谢原作者,转载以备后用 在C# 的应用程序开发中, 我们经常要把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. [php代码审计] php://filter

    筛选过滤应用: 1. 字符串过滤器: string.rot13 对字符串执行ROT13转换 string.toupper转换为大写 string.tolower 转换为小写 string.strip_ ...

  2. 线程工具类 - CyclicBarrier(循环栅栏)

    CyclicBarrier官方文档 一.原理 CyclicBarrier是另外一种多线程并发控制实用工具.它和CountDownLatch非常类似,它也可以实现线程的计数等待,但它的功能比CountD ...

  3. Linux学习-MySQL的主从复制高可用性解决方案MHA

    一.MHA简介 1.MHA Master High Availability,对主节点进行监控,可实现自动故障转移至其它从节点:通过提升某一从节点为新的主节点,基于主从复制实现,还需要客户端配合实现, ...

  4. xcode7 添加个人账户 is not on any development teams

    XCODE7已经可以免费真机测试, 但添加个人账户后,显示 is not on any development teams , 解决办法: 点击 “-” 删除当前账户,退出XCODE重新打开再添加即可 ...

  5. php strspn()函数 语法

    php strspn()函数 语法 作用:返回字符串中包含某些字符的数目.大理石平台厂家 语法:strspn(string,charlist,start,length) 参数: 参数 描述 strin ...

  6. JS中的Date对象

    1.构造函数 Date 对象可以通过构造函数来生成,Date 的构造函数可以放入四种不同的参数 1.1.new Date() ,返回此时的本地日期时间的date对象 let d = new Date( ...

  7. Android签名机制之---签名验证过程详解

    一.前言 今天是元旦,也是Single Dog的嚎叫之日,只能写博客来祛除寂寞了,今天我们继续来看一下Android中的签名机制的姊妹篇:Android中是如何验证一个Apk的签名.在前一篇文章中我们 ...

  8. Python Web框架本质——Python Web开发系列一

    前言:了解一件事情本质的那一瞬间总能让我获得巨大的愉悦感,希望这篇文章也能帮助到您. 目的:本文主要简单介绍Web开发中三大基本功能:Socket实现.路由系统.模板引擎渲染. 进入正题. 一. 基础 ...

  9. C#中如何通过点击按钮切换窗口

    实现方法如下: 1.设计  首先在左侧放一个panel,右侧放一个panel(命名为pnlMain),调整大小,在左侧panel里放置两个按钮(多个按钮同理) 2.在按钮里面写方法 在[命名规范检查] ...

  10. GCD 和 NSOperationQueue 的差别

    http://stackoverflow.com/questions/10373331/nsoperation-vs-grand-central-dispatch http://www.cocoach ...