Dispatcher.CurrentDispatcher与Application.Current.Dispatcher

ken*_*ken 72 .net wpf dispatcher

Dispatcher.CurrentDispatcher(in System.Windows.Threading)和Application.Current.Dispatcher(in System.Windows)之间有什么区别?

我的直觉告诉我,Application.Current.Dispatcher永远不会改变,并且对当前应用程序中的所有线程都是全局的,同时Dispatcher.CurrentDispatcher可能会Dispatcher根据调用它的线程创建一个新实例.

那是对的吗?

如果是,Dispatcher.CurrentDispatcher主要用于多线程UI 的目的是什么?

Jon*_*Jon 88

我的直觉告诉我,Application.Current.Dispatcher将永远不会更改并且对当前应用程序中的所有线程都是全局的,而Dispatcher.CurrentDispatcher可能会根据调用它的线程创建Dispatcher的新实例.

那是正确的.

此外,Dispatcher.CurrentDispatcher从非UI线程访问没有任何意义.除非你打电话Dispatcher.Run,它什么都不做,进入无限消息循环不是你想要在工作线程中做的事情.

所以:

  • 在最常见的情况下,您的应用程序只有一个UI线程,Application.Current.Dispatcher并且Dispatcher.CurrentDispatcher在UI线程内将返回相同的实例.你使用哪一个只是一个偏好问题.

  • 如果您的应用程序有多个UI线程,那么每个线程DispatcherObject将永久地与构建时创建的UI线程的调度程序相关联.在这种情况下,Application.Current.Dispatcher将引用您的应用程序生成的线程的调度程序; 您将无法使用它将消息发布到其他UI线程拥有的控件.

  • 谢谢你的解释,但是你的意思是"除非你打电话给Dispatcher.Run,​​它什么也不会做"?我已经从非UI线程使用了CurrentDispatcher,而Invoke确实调用了一个委托.你是说只是在调用线程上调用委托? (2认同)
  • @ken:`Invoke`和朋友通常"打包"(marshal,如果你愿意)将方法调用到Win32消息中并将其发布到消息队列中,消息循环(调度程序循环)最终将其提取并执行调用.由于没有调度程序循环(如果您在该循环中*您的*代码将不会运行),调用将永远不会发生.所以我假设`Invoke`首先检查你是否已经在`CurrentDispatcher`线程作为优化,如果你在现场执行调用而不是编组.您可以通过检查`Thread.ManagedThreadId`来验证这一点. (2认同)

小智 19

简而言之...

Dispatcher.CurrentDispatcher获取当前线程的调度程序.因此,如果您正在从后台进程中查找UI线程的Dispatcher,请不要使用它.

Application.Current.Dispatcher 将始终为您提供UI线程的调度程序,因为这是旋转唯一Application实例的线程.


H.B*_*.B. 8

我的直觉告诉我,Application.Current.Dispatcher将永远不会更改并且对当前应用程序中的所有线程都是全局的,而Dispatcher.CurrentDispatcher可能会根据调用它的线程创建Dispatcher的新实例.

这是正确的,它Application.Current.Dispatcher是应用程序的实例属性,在构造时分配给当前线程的调度程序.并且作为Dispatcher.CurrentDispatcher指出的文件:

获取当前正在执行的线程的Dispatcher,并创建一个新的Dispatcher(如果尚未与该线程关联).


如果是,Dispatcher.CurrentDispatcher的目的主要是针对多线程UI吗?

可能,我在获取后台线程的调度程序时没有遇到任何用处,因为您通常没有属于它们的UI元素,您可能希望分派操作.