WPF使用Dispatcher

解决bug过程中,遇到线程冲突的问题,记录一下。

Dispatcher介绍

      微软在WPF引入了Dispatcher,那么这个Dispatcher的主要作用是什么呢?
Dispatcher的作用是用于管理线程工作项队列。
主线程负责接收输入、处理事件、绘制屏幕等工作,这样一来,UI界面是主线程创建的,因为子线程不能直接更新由主线程维护的UI界面,所有调用Dispatcher更新UI。

      不管是WinForm应用程序还是WPF应用程序,实际上都是一个进程,一个进程可以包含多个线程,其中有一个是主线程,其余的是子线程。在WPF或WinForm应用程序中,主线程负责接收输入、处理事件、绘制屏幕等工作,为了使主线程及时响应,防止假死,在开发过程中对一些耗时的操作、消耗资源比较多的操作,都会去创建一个或多个子线程去完成操作,比如大数据量的循环操作、后台下载。这样一来,由于UI界面是主线程创建的,所以子线程不能直接更新由主线程维护的UI界面。

      Dispatcher的作用是用于管理线程工作项队列,类似于Win32中的消息队列,Dispatcher的内部函数,仍然调用了传统的创建窗口类,创建窗口,建立消息泵等操作。Dispatcher本身是一个单例模式,构造函数私有,暴露了一个静态的CurrentDispatcher方法用于获得当前线程的Dispatcher。对于线程来说,它对Dispatcher是一无所知的,Dispatcher内部维护了一个静态的 List _dispatchers, 每当使用CurrentDispatcher方法时,它会在这个_dispatchers中遍历,如果没有找到,则创建一个新的Dispatcher对 象,加入到_dispatchers中去。Dispatcher内部维护了一个Thread的属性,创建Dispatcher时会把当前线程赋值给这个 Thread的属性,下次遍历查找的时候就使用这个字段来匹配是否在_dispatchers中已经保存了当前线程的Dispatcher。


实例:WPF更新UI

方式一

new Thread(()=>{

    this.Dispatcher.Invoke(new Action(()=>{

        //通知主线程去完成更新

    }));

}).Start();

 方式二

Application.Current.Dispatcher.Invoke(new Action(() => {

    Application.Current.MainWindow.Title = "我修改过的窗体标题";

}));

 方式三:异步机制

var task = Application.Current.Dispatcher.BeginInvoke(new Action(() => {

    Application.Current.MainWindow.Title = "我修改过的窗体标题";

}));

task.Completed += new EventHandler(task_Completed);

static void task_Completed(object sender, EventArgs e)

{

    MessageBox.Show("任务已经完成");

}

小结

        在WPF中,所有的WPF对象都派生自DispatcherObject,DispatcherObject暴露了Dispatcher属性用来取得创建 对象线程对应的Dispatcher。DispatcherObject对象只能被创建它的线程所访问,其他线程修改 DispatcherObject需要取得对应的Dispatcher,调用Invoke或者BeginInvoke来投入任务。Dispatcher的一些设计思路包括 Invoke和BeginInvoke等从WinForm时代就是一直存在的,只是使用了Dispatcher来封装这些线程级的操作。

参照连接:

WPF Dispatcher介绍 - microsoftzhcn - 博客园 (cnblogs.com)

WPF入门教程系列四——Dispatcher介绍 - DotNet菜园 - 博客园 (cnblogs.com)

你可能感兴趣的:(WPF,C#,wpf,c#)