以下约定之间的主要区别是什么。
首先:
Task myTask = new Task(()=>
{
// executable statements
});
myTask.Start();
第二
Task.Run(()=>
{
// executable statements
});
第三
Task.Factory.StartNew(() =>
{
// executable statements
});
答案 0 :(得分:8)
首先,这个信息可以通过简单的谷歌获得。
一个。来自MSDN "Task.Factory.StartNew" vs "new Task(...).Start"
使用TPL,有几种方法可以创建和启动新任务。一种方法是使用构造函数进行任务,然后调用Start方法,例如
new Task(...).Start();
另一种是使用
TaskFactory
的StartNew方法,例如Task.Factory.StartNew(...);
这引出了一个问题......你何时以及为什么要使用一种方法而不是另一种?
一般情况下,我总是建议使用
Task.Factory.StartNew
,除非特定情况提供了使用构造函数后跟Start的令人信服的理由。我推荐这个有几个原因。首先,它通常更有效率。例如,我们在TPL中需要非常小心,以确保在同时从多个线程访问任务时,会发生“正确”的事情。Task
只执行一次,这意味着我们需要确保从多个线程同时多次调用任务的Start方法只会导致任务被安排一次。这需要同步,并且同步具有成本。如果使用任务的构造函数构造任务,则在调用Start
方法时支付此同步开销,因为我们需要防止另一个线程同时调用Start的可能性。但是,如果您使用Task.Factory.StartNew
,我们知道在我们将任务引用交还给您的代码时已经安排了任务,这意味着线程不再可以竞争调用Start,因为每个拨打Start
将失败。因此,对于StartNew
,我们可以避免额外的同步成本,并为调度任务采取更快的路径。
B中。来自MSDN Task.Run vs Task.Factory.StartNew
因此,在.NET Framework 4.5 Developer Preview中,我们引入了新的
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
任务的行为方式。您可以控制任务应排队到的位置的调度程序并运行。您可以使用接受对象状态的重载,这对于性能敏感的代码路径可以用来避免闭包和相应的分配。但是,对于简单的情况,Task.Run
是你的朋友。
我希望这会有所帮助。