WinForm跨线程访问问题
序言
方案一:
去掉线程访问主线程UI控件的安全检查(不推荐)
Control.CheckForIllegalCrossThreadCalls = false;
方案二:
使用委托,将对主线程的UI控件操作推送了该线程的消息队列里,使用的方法为:Invoke方法和BeginInvoke方法,前一个是同步方法,后一个为异步方法;
使用async 关键字可避免主线程等待
this.BeginInvoke(new Action(async () => { label1.Text = $"Count:{Count},Time: {DateTime.Now.ToString()} "; await Task.Delay(5000); label1.Text = $"Finished {DateTime.Now.ToString()} "; }));
方案三:
使用同步上下文:SynchronizationContext方法,该方法是取得主线程的上下文信息,然后在子线程将访问UI控件方法推送到UI上下文的消息队列里,使用POST或者Send;
方案四:
在命名空间: System.ComponentModel 里有个BackgroundWorker类,它是在一个单独的线程里执行
C#中禁止跨线程直接访问控件,InvokeRequired是为了解决这个问题而产生的,当一个控件的InvokeRequired属性值为真时,说明有一个创建它以外的线程想访问它。
子线程更新主线程方法
Control的Invoke和BeginInvoke
Application.DoEvents();
Application.DoEvents可以防止界面停止响应
private void button1_Click(object sender, EventArgs e) { for (int i = 0; i < 10000; i++) { label1.Text = i.ToString(); Application.DoEvents(); } }
测试了一下,没有Application.DoEvents()的时候,Label基本处于假死机状态,最后显示一个9999,加上后会数字变换正常显示。
如果没有加上DoEvents的话,由于循环时间会比较久就会出现假死的状态,而且程序不能处理其他的事件。而如果加上DoEvents的话就会对文本框的值实时响应,给用户带来较好的用户体验,可是DoEvents也带来了效率上的问题,处理同样的一个事件调用了DoEvents后效率降低了好几倍,这也是为什么要慎用的原因了。
理解C#中的ExecutionContext vs SynchronizationContext
为什么需要SynchronizationContext
众所周知,.NET Framework 支持几种不同类型的应用程序,而每种应用程序所支持的线程模型也不相同。
Console、Windows Service应用程序不对线程做任何限制,即在这两种应用程序中,线程可做任何它想做的事;
而Windows Forms(从.NET Framework 2.0开始)、WPF、Silverlight支持的线程模型是:窗体控件只允许创建它的线程可以对其进行更新。
如果是非创建线程对其更新,在VS中调试时,则会抛出InvalidOperationException异常,并提示:从不是创建控件的线程访问它。
虽然在非调试状态下不会抛出这个异常,但这样做不是线程安全的。
在Windows Forms中,为了解决从非创建线程更新的问题,我们可以通过调用Form.CheckForIllegalCrossThreadCalls属性并将其值设为false,
正如前面所说,这不是线程安全的,所以不建议这样做。于是MS为我们提供了一种新的更新方式:通过委托转到创建线程进行更新。
什么是SynchronizationContext
SynchronizationContext在通讯中充当传输者的角色,实现功能就是一个线程和另外一个线程的通讯。
需要注意的是,不是每个线程都附加SynchronizationContext这个对象,只有UI线程是一直拥有的。故获取SynchronizationContext也只能在UI线程上进行SynchronizationContext context = SynchronizationContext.Current;
资料
SynchronizationContext对Windows Forms窗体控件的更新方法
线程之间的通讯---SynchronizationContext
https://www.cnblogs.com/kiminozo/archive/2012/02/06/2340609.html
https://www.cnblogs.com/xiaoxiaotank/p/13666913.html
https://www.cnblogs.com/mqxs/p/4288644.html