【问题标题】:Application Dispatcher and Control Dispatcher应用程序调度程序和控制调度程序
【发布时间】:2011-11-26 16:58:19
【问题描述】:

假设我有名为“button1”的控制按钮和名为“doSomething”的函数。从另一个线程调用函数“doSomething”。

我有两种方法可以从 UI 线程调用函数 doSomething。

首先,来自控制按钮调度器

this.button1.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));

其次,来自应用调度程序

this.Dispatcher.BeginInvoke(new Action(() => { doSomething(); }));

结果是一样的,真​​正不同的是什么?

【问题讨论】:

    标签: wpf controls dispatcher


    【解决方案1】:

    同一线程拥有的所有控件都引用了相同的调度程序实例。没有区别。

    【讨论】:

    • 你的意思是dispatcher是静态的并且由一个线程(UI线程)拥有?
    • @brian:从静态字段是静态的意义上说,它不是静态的,每个线程只有一个实例。并且应用程序引用了 UI-tread 的调度程序。
    • 该函数继承自它们的父级(窗口或控件)并由 UI 线程拥有,对吗?
    • @brian:它不是继承的,它来自基类DispatcherObject的构造函数,MSDN says是什么:“在构造时,一个DispatcherObject存储了一个对链接到的Dispatcher的引用当前运行的线程。”
    【解决方案2】:

    所有 UI 控件(正常创建)共享同一个调度程序实例。该调度程序正在处理 UI 线程。如果您在背景线程上创建一些控件,它将在该线程上创建新的调度程序,这不会很好。 避免 WinForms 和 WPF 中的线程和 UI 控件出现大多数问题的最佳方法是使用System.Threading.SynchronizationContext.Current。工作流程很简单:您在 UI 线程上获得 System.Threading.SynchronizationContext.Current 并将其保存在某处(例如在公共静态字段中)。然后,每当您想在 UI 线程上运行一些代码时,您都可以访问该持久化的 SynchronizationContext 实例并使用其 SendPost 方法。它将在线程上运行您的委托,其中实现了 SynchronizationContext(对于 UI 线程上的当前情况)。它也很聪明,可以使用当前的调用方式(WinForms 的消息循环和 WPF 的调度程序),而且如果您已经从 UI 线程调用,它只会同步运行您的委托。 请记住,只有在当前 UI 线程上创建第一个控件后,您才应该获得 SynchronizationContext,因为之后将立即初始化 SynchronizationContext

    【讨论】:

    • 单例调度器呢?我认为调度程序比 SynchronizationContext 简单得多。
    • 当然,你可以将Dispatcher保存为单例。只是 SynchronizationContext 在使用方面几乎是一样的,而且你的代码对于 WinForms、Wpf 和可能未来的框架都是统一的。
    • 简单地使用 Application.Current.Dispatcher.Invoke(...) 来调用 UI 线程上的方法不好吗?
    【解决方案3】:

    在大多数情况下,我们只有一个 UI 线程。所以,你打电话没有任何区别

    control.Dispatcher(which comes inherited from DispatcherObject parent of the controls).
    
    or 
    
    Disptacher.Current.
    

    但在某些情况下,您最终会拥有多个调度程序。 因此,在这种情况下,Control.Dispatcher 会有所帮助,因为它将找出当前调度程序以尊重线程关联。在这个 Dispatcher.Current 将无济于事。

    在一个场景中,具有用于显示繁忙指示器的专用线程(带有调度程序)作为默认 UI 线程正在忙于呈现大量控件列表。

    但是,使用 SynchronizationContext 是避免此类问题的另一种方法。但是,如果不再需要该上下文或线程,或者它已被任何其他开发人员设置为 null,该怎么办。所以,在我看来,选择 Control.Dispatcher 总是明智的。

    【讨论】:

      猜你喜欢
      • 2016-06-30
      • 2018-07-29
      • 2013-09-15
      • 2023-04-04
      • 2015-05-28
      • 1970-01-01
      • 2012-02-03
      • 1970-01-01
      相关资源
      最近更新 更多