【问题标题】:Dispatcher.CurrentDispatcher vs. Application.Current.DispatcherDispatcher.CurrentDispatcher 与 Application.Current.Dispatcher
【发布时间】:2012-05-04 12:40:06
【问题描述】:

Dispatcher.CurrentDispatcherSystem.Windows.Threading)和Application.Current.DispatcherSystem.Windows)有什么区别?

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

对吗?

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

【问题讨论】:

    标签: .net wpf dispatcher


    【解决方案1】:

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

    没错。

    此外,从非 UI 线程访问 Dispatcher.CurrentDispatcher 毫无意义。除非您调用 Dispatcher.Run,否则它什么也不会做,并且进入无限消息循环并不是您想要在工作线程中执行的操作。

    所以:

    • 在最常见的场景中,您的应用只有一个 UI 线程,来自 UI 线程内的Application.Current.DispatcherDispatcher.CurrentDispatcher 将返回相同的实例。您使用哪一个只是偏好问题。

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

    【讨论】:

    • 感谢您的解释,但您所说的“除非您调用 Dispatcher.Run,​​否则它什么也不做”是什么意思?我从非 UI 线程中使用了 CurrentDispatcher,并且 Invoke 确实调用了委托。你的意思是只在调用线程上调用委托?
    • @ken:Invoke 和朋友通常“打包”(marshal,如果您愿意)一个方法调用到 Win32 消息中并将其发布到消息队列中,消息循环(调度程序循环) 最终提取它并执行调用。由于没有调度程序循环(如果您在该循环中您的代码将不会运行),调用将永远不会真正发生。所以我假设Invoke 首先检查你是否已经在CurrentDispatcher 线程中作为优化,如果你是当场执行调用而不是编组。您可以通过检查Thread.ManagedThreadId 来验证这一点。
    • 您将无法使用它向您的其他 UI 线程拥有的控件发布消息。 那么,您的平均 WPF 应用程序中有多少个 UI 线程?
    • @Will:一:“如果你的应用只有一个 UI 线程(很可能)...”。您认为需要进一步澄清吗?
    • @Will:编辑以增加相关部分的可见性。谢谢你告诉我。
    【解决方案2】:

    简单地说……

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

    Application.Current.Dispatcher 将始终为您提供 UI 线程的调度程序,因为这是启动唯一应用程序实例的线程。

    【讨论】:

      【解决方案3】:

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

      没错,Application.Current.Dispatcher 是应用程序的实例属性,在构造时被分配为当前线程的调度程序。正如Dispatcher.CurrentDispatcher 的文档指出的那样:

      获取当前正在执行的线程的 Dispatcher,如果尚未与线程关联,则创建一个新的 Dispatcher。


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

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

      【讨论】:

        猜你喜欢
        • 2013-11-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-03-23
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多