WPF BackgroundWorker与Dispatcher

lam*_*ora 31 wpf multithreading dispatcher backgroundworker

在我的WPF应用程序中,我需要执行异步操作,然后我需要更新GUI.这件事我不得不在不同的时刻做不同的操作.我知道两种方法:Dispatcher和BackgroundWorker.

因为当我选择它时我会很难回去,我问你:什么更好?选择一个而不是另一个的原因是什么?

谢谢!Pileggi

Ale*_*ven 38

Dispatcher和其他线程方法之间的主要区别在于Dispatcher实际上并不是多线程的.Dispatcher控制控件,这需要一个线程才能正常运行; Dispatcher的BeginInvoke方法将事件排队等待以后执行(取决于优先级等),但仍在同一个线程上.

另一方面,BackgroundWorker实际上是在一个单独的线程中调用它的同时执行代码.它也比真正的线程更容易使用,因为它自动同步(至少我认为我记得这个)与应用程序的主线程,负责控件和消息队列(在WPF的情况下为Dispatcher线程) Silverlight),因此从后台线程更新控件时不需要使用Dispatcher.Invoke(或WinForms中的Control.Invoke),尽管可能并不总是建议这样做.

正如里德所说,任务并行库是一个很好的选择.

编辑:进一步观察.

正如我上面所说,Dispatcher并不是真正的多线程; 它只会给出它的错觉,因为它会运行你在另一个时间传递给它的委托.我只在代码真正处理应用程序的View方面时使用Dispatcher - 即控件,页面,窗口等等.当然,它的主要用途实际上是触发来自其他线程的操作以正确地或在正确的时间更新控件(例如,只有在使用Dispatcher完成一些控件完全呈现/布局后才设置焦点,因为在WPF渲染中并不完全确定性).

BackgroundWorker可以使多线程代码比通常情况简单得多; 这是一个简单的概念,最重要的是(如果有意义的话)你可以从中派生自定义工作者,它可以是异步执行单个任务的专用类,具有可用作参数,进度通知和取消等的属性我总是发现BackgroundWorker是一个巨大的帮助(除非我必须从中得到它以保持原始线程的文化以保持正确的本地化:P)

最强大但也很困难的路径是使用最低级别的System.Threading.Thread; 然而,如果出现问题则很容易,因为它并不是真正推荐的.多线程编程很难,这是给定的.但是,如果你想要了解所有方面,那么有很多很好的信息:我们的好伙伴Jon Skeet的这篇优秀文章立刻浮现在脑海中(文章的最后一页也有很多非常有趣的链接).

在.Net 4.0中,我们有一个不同的选项,即任务并行库.我还没有使用它,但是从我看到的它令人印象深刻(PLINQ简直太棒了).如果你有好奇心和资源去学习它,那就是我所推荐的(毕竟不应该花那么多东西学习).


Ree*_*sey 8

如果您正在执行单个操作,它提供进度通知和完成事件,那么BackgroundWorker很不错.但是,如果您要多次运行相同的操作或多次操作,那么您将需要多个BackgroundWorker.在这种情况下,它会变得很麻烦.

如果您不需要进度事件,那么使用ThreadPool和Dispatcher可以更简单 - 特别是如果您要进行相当多的不同操作.

但是,如果C#4是一个选项,那么使用任务并行库也是一个很好的选择.这使您可以使用当前的SynchronizationContext设置继续任务,在许多情况下,它提供了更简单,更简洁的模型.有关详细信息,请参阅关于此主题的博文.