关于任务编程的问题

Ste*_*ald 3 c# task-parallel-library c#-5.0

以下约定之间的主要区别是什么?

第一:

Task myTask = new Task(()=>
{
     // executable statements
});
myTask.Start();
Run Code Online (Sandbox Code Playgroud)

第二:

Task.Run(()=>
{
  // executable statements
});
Run Code Online (Sandbox Code Playgroud)

第三:

  Task.Factory.StartNew(() =>
  {
       // executable statements
  });
Run Code Online (Sandbox Code Playgroud)

Moo*_*ght 8

首先,这个信息可以通过简单的谷歌获得.

A.从MSDN"Task.Factory.StartNew"vs"new Task(...).Start"

使用TPL,有几种方法可以创建和启动新任务.一种方法是使用构造函数进行任务,然后调用Start方法,例如

new Task(...).Start();
Run Code Online (Sandbox Code Playgroud)

另一种是使用TaskFactory例如StartNew方法

Task.Factory.StartNew(...);
Run Code Online (Sandbox Code Playgroud)

这引出了一个问题......何时以及为什么你会使用一种方法而不是另一种方法?

一般来说,我总是建议使用Task.Factory.StartNew除非特定情况提供使用构造函数后跟Start的令人信服的理由.我推荐这个有几个原因.首先,它通常更有效率.例如,我们在TPL中需要非常小心,以确保在同时从多个线程访问任务时,会发生"正确"的事情.A Task只执行一次,这意味着我们需要确保同时从多个线程多次调用任务的Start方法只会导致任务被安排一次.这需要同步,并且同步具有成本.如果使用任务的构造函数构造任务,则在调用Start方法时支付此同步开销,因为我们需要防止另一个线程同时调用Start的机会.但是,如果您使用Task.Factory.StartNew,我们知道任务将在我们将任务引用交还给您的代码时进行调度,这意味着线程无法再竞争调用Start,因为每次调用都Start将失败.因此,StartNew我们可以避免额外的同步成本,并为调度任务采取更快的路径.

B.从MSDN Task.Run到Task.Factory.StartNew

因此,在.NET Framework 4.5 Developer Preview中,我们引入了新Task.Run方法.这绝不是过时的Task.Factory.StartNew,而应该简单地被认为是一种快速的使用方式,Task.Factory.StartNew而无需指定一堆参数.这是捷径.实际上,Task.Run实际上是根据用于的相同逻辑实现的Task.Factory.StartNew,只是传递一些默认参数.当你传递ActionTask.Run:

Task.Run(someAction);
Run Code Online (Sandbox Code Playgroud)

这完全等同于:

Task.Factory.StartNew(someAction, 
    CancellationToken.None, TaskCreationOptions.DenyChildAttach, TaskScheduler.Default);
Run Code Online (Sandbox Code Playgroud)

通过这种方式,Task.Run可以而且应该用于最简单的卸载一些要在ThreadPool上处理的工作(什么TaskScheduler.Default目标)的情况.这并不意味着Task.Factory.StartNew永远不会再使用; 离得很远. Task.Factory.StartNew仍然有许多重要的(虽然更高级)用途.您可以控制TaskCreationOptions任务的行为方式.您可以控制任务应排队到的位置的调度程序并运行.您可以使用接受对象状态的重载,这对于性能敏感的代码路径可以用来避免闭包和相应的分配.但是,对于简单的情况,Task.Run是你的朋友.

我希望这有帮助.