为什么选择System.Threading over BackgroundWorker?

时间:2012-09-13 01:53:01

标签: c# .net multithreading

为什么我决定选择直接使用System.Threading在BackgroundWorker上工作,如果最后一个为我提供了treading managemnet?

我看不到无法使用BackgroundWorker替换System.Threading

的情况

4 个答案:

答案 0 :(得分:7)

BackgroundWorker自.NET 2.0以来一直存在,旨在帮助编写将在后台线程中运行的代码,而不是陷入UI线程。它最初出现在Windows Forms中,但也适用于WPF或任何未来注册同步上下文的UI框架。它允许您将进度和结果报告回UI线程,而无需处理InvokeRequired / BeginInvoke以及支持取消。

任务并行库(TPL)是在.NET 4中引入的,旨在为异步任务建模。这些任务是异步的,可能会也可能不会在另一个线程上运行。不在另一个线程上运行的东西的示例是异步IO和需要在UI上运行的任务(同时仍然是异步的)。此任务隐喻还支持期货(或延续),以便您可以将任务与ContinueWith链接在一起,有时使用特定的同步上下文,以便您可以执行诸如在UI线程上运行任务(以更新UI,例子)。

任务还支持取消,多个任务可以共享取消令牌,因此请求的取消可以取消多个任务。

其中一个差异是Task没有将回复报告回UI的固有方法。当然这是可能的,但它并没有内置到接口中。 Task也支持取消。

如果您只想在后台执行一项操作,并且您特别想要回复报告进度等UI,我建议您BackgroundWorker。否则,我通常建议使用Task<T>(如果不需要结果,则使用Task)。 Task本身就用于C#5 async / await语法...

答案 1 :(得分:3)

我希望您尝试考虑每种方法的用意。

BackgroundWorker主要是在一开始就为Windows Forms设计的(虽然它也可以在WPF中使用),它只提供一些异步操作的功能。将它与System.Threading下的所有类进行比较,您可以看到BackgroundWorker显然是建立在它们之上的。

使用System.Threading下的所有类,您可以构建自己的BackgroundWorker并享受更多功能并控制代码。这里的难点是敏锐的学习曲线和调试挑​​战。

因此,如果您认为BackgroundWorker足够,请继续使用它。如果您发现缺少某些内容,System.Threading中的构建块可以成为您的帮助者。

在.NET Framework 4中,Microsoft在System.Threading上设计了另一组类,名为基于任务的异步模式,

http://www.microsoft.com/en-us/download/details.aspx?id=19957

使用它,您几乎可以忘记BackgroundWorker,因为它提供了更多功能并为您提供了足够的控制,同时不需要您深入了解直接使用System.Threading的复杂性。

答案 2 :(得分:2)

我有blog post on the subject

简而言之,如果可能,您应该使用async Task s。 Thread确实提供了一些额外的“旋钮” - 例如Priority - 但通常这些旋钮不是必需的,程序员通常会以错误的方式将它们转换。

答案 3 :(得分:-1)

例如,您无法在BackgroundWorker上设置调度优先级,但可以在线程上设置。

Thread.Priority Property

对我的回答提出质疑的评论继续引用Task和ThreadPool。陈述的问题不是关于Task或ThreadPool,也不是我的答案。

请参阅上面链接中的代码示例。它清楚地表明在启动线程之前分配优先级并控制启动线程。

完整的代码示例:

PriorityTest priorityTest = new PriorityTest();
ThreadStart startDelegate =  new ThreadStart(priorityTest.ThreadMethod);

Thread threadOne = new Thread(startDelegate);
threadOne.Name = "ThreadOne";
Thread threadTwo = new Thread(startDelegate);
threadTwo.Name = "ThreadTwo";

threadTwo.Priority = ThreadPriority.BelowNormal;
threadOne.Start();
threadTwo.Start();

// Allow counting for 10 seconds.
Thread.Sleep(10000);
priorityTest.LoopSwitch = false;

我测试了这个并且ThreadTwo在ThreadPriority.BelowNormal上启动并完成。在我的测试中,threadOne处理大约10X作为threadTwo。

BackGroundWorker没有Priority属性。 BackgroundWorker以默认优先级Normal开始。 BackgroundWorker线程优先级可以在DoWork中更改,但是一旦工作开始改变线程的优先级显然不一样。