架构师_程序员_码农网

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 12503|回复: 0

[交流] .net/c# SynchronizationContext详解

[复制链接]
发表于 2018-3-15 11:51:07 | 显示全部楼层 |阅读模式
看过很多介绍文章介绍如何在后台线程更新主界面的,多数都是使用Control.Invoke, Control.BeginInvoke。这些都是很好的解决方案,不过有两个问题:

1. 必须的引用System.Windows.Forms,然后 using System.Windows.Forms

2. 代码结构比较零乱。(实际上这个也是#1 导致的)

微软提供了另外一个比较优雅的解决方案,就是 System.Threading. SynchronizationContext。 可以看出,它不在 namesapce System.Windows.Forms 里面,因此我们可以理直气壮地用在BusinessLaryer, Controler,甚至 module 里面。

而且它使用非常方便,只需要关注下面两个方法即可:

1.      Send:发送界面更新请求至主线程,阻塞当前线程直至返回。

2.      Post:发送界面更新请求至主线程,不阻塞当前线程。

实际上,他们都是同一个方法,只是 send 是同步,post 是异步


在Form1 form = new Form1()之前,SynchronizationContext对象是为空,而当实例化Form1窗体后,SynchronizationContext对象就被附加到这个线程上了。所以可以得出答案了:当Control对象被创建的同时,SynchronizationContext对象也会被创建并附加到线程上。所有在使用时,一定要等窗体InitializeComponent(); 这个完成后 它才能得到一个不这NULL的对象


最后SynchronizationContext的Sendt()和Post()二个方法的区别:

Send() 是简单的在当前线程上去调用委托来实现(同步调用)。也就是在子线程上直接调用UI线程执行,等UI线程执行完成后子线程才继续执行。

Post() 是在线程池上去调用委托来实现(异步调用)。这是子线程会从线程池中找一个线程去调UI线程,子线程不等待UI线程的完成而直接执行自己下面的代码。
测试代码:

结果:

UI主线程:1
Thread线程:5
SynchContext:1


总结:在UI线程上的SynchronizationContext对象,无论是在主线程还是在线程里面调用,都会是在主线程上面去执行的,所以,在有大量耗时的代码时,会导致UI界面卡顿或者假死

其实在UI线程中使用的并不是SynchronizationContext这个类,而是WindowsFormsSynchronizationContext这个东东。



QQ截图20180315111932.jpg

System.Threading.SynchronizationContext源码:


WindowsFormsSynchronizationContext源码:







上一篇:C# 优化程序的四十七种方法
下一篇:.net/c# 上海拍沪牌小助手[附源码]
码农网,只发表在实践过程中,遇到的技术难题,不误导他人。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

免责声明:
码农网所发布的一切软件、编程资料或者文章仅限用于学习和研究目的;不得将上述内容用于商业或者非法用途,否则,一切后果请用户自负。本站信息来自网络,版权争议与本站无关。您必须在下载后的24个小时之内,从您的电脑中彻底删除上述内容。如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。如有侵权请邮件与我们联系处理。

Mail To:help@itsvse.com

QQ|手机版|小黑屋|架构师 ( 鲁ICP备14021824号-2 )|网站地图

GMT+8, 2024-3-29 02:29

Powered by Discuz! X3.4

Copyright © 2001-2021, Tencent Cloud.

快速回复 返回顶部 返回列表