【问题标题】:Use of Application.Current.Dispatcher for events outside dispatcher thread将 Application.Current.Dispatcher 用于调度程序线程之外的事件
【发布时间】:2017-06-27 04:40:39
【问题描述】:

问题:“Application.Current.Dispatcher.Invoke”应该放在引发事件的工作线程中还是放在处理事件的 UI 代码中?无论哪种方式都可以正常工作,但更好的做法或区别是什么?

在创建新闻代码的 WPF 应用程序中,我通过 Microsoft.Office.Interop.OutlookItemAdd 事件从新收件箱电子邮件中检索正文文本,然后引发传递正文文本的事件。主视图模型订阅此事件如下。在OutlookReader类中:

private void OnEmailFoundWithSubjectMatchingFilter(_MailItem item)
{
    System.Windows.Application.Current.Dispatcher.Invoke(() =>
    {
        FoundEmailWithSubjectMatchingFilter?.Invoke(this, item.Body);
    });
}

并且,在MainViewModel 类中:

private void HandleEmailFeed(object sender, string e)
{
    //Application.Current.Dispatcher.Invoke(() =>
    //{
    var parser = new MailBodyParser();

    AddFeedItem(parser.Parse(e));
    //});
}

【问题讨论】:

  • 没有一个正确的答案。做任何更符合图书馆用户期望的事情。有时这被称为最小惊讶原则。
  • 我倾向于认为 UI 端应该调用调度程序,因为工作线程不应该真正负责其结果的使用方式。真的想知道是否存在任何技术/性能差异。
  • 我不明白你在问什么。按照惯例,“UI 线程”是调度程序线程。如果您已经在 UI 线程中执行代码,则无需调用 Dispatcher.Invoke()。您将从线程而不是 UI 线程调用Dispatcher.Invoke()
  • 编写线程代码从来都不是一件容易的事,当你不注意时,它有很强的失败诀窍。具有几乎无法诊断的故障模式。这使得不知道您的代码运行什么线程会产生巨大的代码气味。如果您不知道,那么您永远无法证明您的代码是线程安全的。永远不要那样做。
  • 如果担心在不需要的时候使用dispatcher会降低性能,可以使用CheckAccess方法:if (!Application.Current.Dispatcher.CheckAccess()) { // You should use invoke } else { // Invoke isn't required }msdn.microsoft.com/en-us/library/…

标签: c# wpf multithreading


【解决方案1】:

应该将“Application.Current.Dispatcher.Invoke”放在引发事件的工作线程中还是放在处理事件的 UI 代码中?

我会说后者。主要是因为工作线程可能在一个不知道任何System.Windows.Application对象的类库中启动。

因此,工作线程应该简单地引发事件,然后客户端应用程序只负责更新最初创建它们的调度程序线程上的 UI 元素。类库不应该关心甚至知道任何调度程序。

【讨论】:

  • 不知道为什么这被否决了,但是,是的,这将是答案。这是我的第一个问题,正如 Peter Duniho 提到的,我本可以更好地措辞。直到我发帖后我才意识到我真正想要回答的问题是:什么模式/实践最适合处理 WPF 中工作线程和调度程序线程之间的事件?这也可能过于开放,但我会改进它并发布一个新问题。感谢您的回复。
猜你喜欢
  • 1970-01-01
  • 2017-05-07
  • 2014-07-07
  • 2014-09-03
  • 2018-05-25
  • 1970-01-01
  • 2016-05-06
  • 2013-11-30
  • 2015-11-06
相关资源
最近更新 更多