【发布时间】:2017-06-27 04:40:39
【问题描述】:
问题:“Application.Current.Dispatcher.Invoke”应该放在引发事件的工作线程中还是放在处理事件的 UI 代码中?无论哪种方式都可以正常工作,但更好的做法或区别是什么?
在创建新闻代码的 WPF 应用程序中,我通过 Microsoft.Office.Interop.Outlook 和 ItemAdd 事件从新收件箱电子邮件中检索正文文本,然后引发传递正文文本的事件。主视图模型订阅此事件如下。在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