博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
WinForm 界面异步更新数据(方式三)
阅读量:6254 次
发布时间:2019-06-22

本文共 2788 字,大约阅读时间需要 9 分钟。

 

Control 不能在创建它的 Thread 之外被调用。但可以通过 invoke 来保证 Control 线程安全。

在跨线程更新的时候,Control 会检查 CurrentThread 是否为创建 Control 的线程,并报错!

示例代码如下:

private void btnStart_Click(object sender, EventArgs e){     //注意:特地不使用 Timer 控件     Thread thread = new Thread(Fun);     thread.Start(DateTime.Now.ToString());}//报错:线程间操作无效: 从不是创建控件“lblTime”的线程访问它。private void Fun(object datetime){     lblTime.Text = (string)datetime;}

最简单的解决方式是在程序代码中添加如下属性:

        Control.CheckForIllegalCrossThreadCalls = false;

 

在多线程编程中,我们经常要在工作线程中去更新界面显示,而在多线程中直接调用界面控件的方法是错误的做法,Invoke 和 BeginInvoke 就是为了解决这个问题而出现的,使你在多线程中安全的更新界面显示。

将要做的事情放在工作线程中执行,而将对纯粹的界面更新放到 UI 线程中去做,这样也就达到了减轻 UI 线程负担的目的。

 

使用 BeginInvoke 方法解决该问题的代码如下:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms;using System.Threading;namespace Invoke_Test{    public partial class Form1 : Form    {        //private System.Windows.Forms.Label lblTime;        //private System.Windows.Forms.Button btnStart;        public Form1()        {            InitializeComponent();            // 解决方式一            // Control.CheckForIllegalCrossThreadCalls = false;        }        private void btnStart_Click(object sender, EventArgs e)        {            string arg = DateTime.Now.ToString();            // 注意:创建子线程间接调用            Thread thread = new Thread(FunStart);            thread.Start(arg); //arg 给方法传参          }        // 定义调用方法的委托        delegate string FunDelegate(string str);        // 注意:特地使用 FunStart 方法模拟间接调用        private void FunStart(object obj)        {            // 要调用的方法的委托            FunDelegate funDelegate = new FunDelegate(Fun);            /*========================================================             * 使用this.BeginInvoke方法             * (也可以使用this.Invoke()方法)            ========================================================*/            // this.BeginInvoke(被调用的方法的委托,要传递的参数[Object数组])            IAsyncResult aResult = this.BeginInvoke(funDelegate,obj.ToString());            // 用于等待异步操作完成(-1表示无限期等待)            aResult.AsyncWaitHandle.WaitOne(-1);            // 使用this.EndInvoke方法获得返回值            string str = (string)this.EndInvoke(aResult);            MessageBox.Show(str.ToString());        }        // 真正需要执行的方法        private string Fun(string datetime)        {            lblTime.Text = (string)datetime;            return "委托的返回值";        }    }}

Control.InvokeRequired 属性:当前线程不是创建控件的线程时为 true。

也可以认为,在 new Control() 的时候,Control 用一个变量记录下了当前线程,在调用 InvokeRequired 时,返回当前线程是否不等于 new 的时候记录下来的那个线程。

 

Control.Invoke 和 Control.BeginInvoke 就是“发短信”的方法,如果使用 Control.Invoke 发短信,那么甲线程就会像个痴情的汉子,一直等待着乙线程的回音,而如果使用 Control.BeginInvoke 发送短信,那发完短信后,甲线程就会忙活自己的,等乙线程处理完再来瞧瞧。

 示例代码:

 

转自:

转载于:https://www.cnblogs.com/blosaa/archive/2013/05/14/3078374.html

你可能感兴趣的文章
小米武汉总部开工雷军亲自出席:远期在汉要招上万人
查看>>
传贾跃亭将FF股份交给友人代持以规避失信人限制
查看>>
豆盟递交招股书:单季利润1394万 蓝标为第二大股东
查看>>
申小雨命案审理延期至3月5日 警方将翻译嫌犯口供
查看>>
第五届中欧文化艺术节开幕 谭盾“领衔”献艺
查看>>
财政部:2018年全国财政收入超18万亿元 同比增6.2%
查看>>
C罗失点 尤文图斯3:0切沃延续联赛不败纪录
查看>>
湖北整治清退非法码头 为长江“留白增绿”
查看>>
为什么要把网站升级到HTTPS
查看>>
【Hello CSS】序章-起源
查看>>
转行IT要趁早,多迪教育新就业数据告诉你真相
查看>>
JavaScript深入之参数按值传递
查看>>
Fragment总结
查看>>
Flutter进阶:深入探究 ListView 和 ScrollPhysics
查看>>
深入了解virtual dom
查看>>
spring事物应该注意的地方
查看>>
浅析 Vue 2.6 中的 nextTick 方法
查看>>
一篇文章搞懂闭包。
查看>>
结合实际场景谈一谈微服务配置
查看>>
我的前端面试总结(套路篇)
查看>>