翻译自 Stephen Toub 2011年10月24日的博文《Task.Run vs Task.Factory.StartNew》,Stephen Toub 是微软并行计算平台团队的首席架构师。
在 .NET 4 中,Task.Factory.StartNew
是安排新任务的首选方法。它有许多重载提供了高度可配置的机制,通过启用设置选项,可以传递任意状态、启用取消,甚至控制调度行为。所有这些功能的另一面是复杂性。您需要知道什么时候使用哪个重载、提供什么调度程序等等。另外,Task.Factory.StartNew
用起来并不直截干脆,至少对于它的一些使用场景来说还不够快,比如它的主要使用场景——轻松地将工作交付到后台处理线程。
因此,在 .NET Framework 4.5 开发者预览版 中,我们引入了新的 Task.Run
方法。这决不是要淘汰 Task.Factory.StartNew
,而是应该简单地认为这是使用 Task.Factory.StartNew
而不必传递一堆参数的一个便捷方式。这是一个捷径。事实上,Task.Run
实际是按照与 Task.Factory.StartNew
相同的逻辑实现的,只是传入了一些默认的参数。当你传递一个 Action
给 Task.Run
:
Task.Run(someAction);
完全等同于:
Task.Factory.StartNew(someAction, CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
通过这种方式,Task.Run
就可以并且应该被用于大多数通用场景——简单地将工作交给线程池ThreadPool
处理(即参数 TaskScheduler.Default 的目标)。这并不意味着 Task.Factory.StartNew
将不再被使用; 远非如此,Task.Factory.StartNew
还有很多重要的(固然更高级)用途。你可以控制 TaskCreationOptions
来控制任务的行为,可以控制 TaskScheduler
来控制任务的调度和运行,也可以使用接收对象状态的重载,对于性能敏感的代码路径,使用该重载可以避免闭包和相应的内存分配。不过ÿ