对于WPF程序,大家绕不开的一个概念叫做Dispatcher
- 什么是
Dispathcer
WPF程序启动后会有两个线程:UI线程和渲染线程。UI线程会将所有的任务切成小份,放入一个队列进行依次执行,而执行这些工作的object
就是Dispatcher
。对于WPF来说,常见的Dispatcher
概念有三个Application.Current.Dispatcher
,Dispather.CurrentDispatcher
,DispatcherObject.Dispatcher
- 三者的区别
对于大部分的WPF类来说,它们都继承于DispatcherObject
。而每个DispatcherObject
都只能被创建它的DispatcherObject
所操作。这种行为的实现方式就是,在每个DispatcherObject
的操作之前,会调用VerifyAccess
方法,检测当前线程的Dispatcher
(即Dispather.CurrentDispatcher
)和自身的Dispatcher
(即DispatcherObject.Dispatcher
)是否相同。若不相同则会抛出相应的异常。
所以可以从此了解到,Dispather.CurrentDispatcher
是和当前线程相关的Dispathcer
,而DispatcherObject.Dispatcher
是创建这个对象的Dispathcer
。
那么Application.Current.Dispatcher
呢?Application.Current
是一个单例模式,指向的是当前WPF进程的Application
实例。而Application
继承于DispatcherObject
,所以Application.Current.Dispatcher
是一个特殊的DispatcherObject.Dispatcher
- Why not Dispather.CurrentDispatcher
回到主题,为什么我们不推荐使用Dispather.CurrentDispatcher
。
事实上,大家进程使用Dispatcher
的场合是在后台线程更新UI内容。因为所有的UI线程创建的DispatcherObject
对象只能在UI线程操作。因此需要“告诉”UI线程的Dispatcher
去Invoke
一个操作。而此时(后台线程中)UI线程中创建的Application
和DispatcherObject
的Dispatcher
属性都指向UI线程的Dispatcher
对象。而Dispather.CurrentDispatcher
并不是。所以就会出现相应的错误。
参考链接:
本文会经常更新,请阅读原文: https://xinyuehtx.github.io/post/Why-not-Dispather.CurrentDispatcher.html ,以避免陈旧错误知识的误导,同时有更好的阅读体验。
本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名黄腾霄(包含链接: https://xinyuehtx.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 。