在WPF或WinForm应用程序中,主线程负责接收输入、处理事件、绘制屏幕等工作,为了使主线程及时响应,防止假死,在开发过程中对一些耗时的操作、消耗资源比较多的操作,都会去创建一个或多个子线程去完成操作,比如大数据量的循环操作、后台下载。这样一来,由于UI界面是主线程创建的,所以子线程不能直接更新由主线程维护的UI界面
在WPF的例子中,是通过this.Dispatcher.BeginInvoke或者Application.Current.Dispatcher.BeginInvoke去异步更新UI的。业务处理是通过异步Task方法去处理的,而task并非UI线程,所以不能直接在task里面直接更新UI.Dispatcher就是UI线程
System.Windows.Threading.DispatcherObject 类:从图中看WPF 中的使用到的大部分控件与其他类大多是继承 DispatcherObject 类,它提供了用于处理并发和线程的基本构造
所有的UI都是继承自DependencyObject和DispatcherObject,我们通常为UI设置依赖属性,我们在后台改变依赖属性的值,也就是访问依赖对象DependencyObject,即UI,这个时候往往要用Dispatcher获取当前UI的线程(即获取对DispatcherObject和DependencyObject的访问的权力)
WinForm的例子中是使用Control.Invoke去使用UI线程。也可以设置Control.CheckForIllegalCrossThreadCalls = false;以非线程安全的方式直接访问UI的控件
- 非泵式等待错误
错误详细如下:
CLR 无法从 COM 上下文 0x21be4d0 转换为 COM 上下文 0x21be720,这种状态已持续 60 秒。拥有目标上下文/单元的线程很有可能执行的是非泵式等待或者在不发送 Windows 消