Task.WaitAll()的行为如何?

时间:2015-10-03 06:07:23

标签: c# c#-5.0

我创建了一个Task列表,如下所示:

public void A()
{

}

public void B()
{

}

public void C()
{

}

public void Ex()
{
   Task.WaitAll(Task.Factory.StartNew(A), Task.Factory.StartNew(B), Task.Factory.StartNew(C));
   var p=true;
}

现在我的问题是。列表中的所有任务是逐个执行还是并行执行。

  

P =真

“p”是在所有任务完成之后还是在完成之前设置的?

2 个答案:

答案 0 :(得分:7)

对于第一个问题:

  

这些任务是逐个执行还是异步执行。

(在这里,我想你的意思是同时,这不完全一样)

使用StartNew将在当前TaskScheduler中运行您的任务。默认情况下,这意味着它将使用ThreadPool,如果线程池中有任何可用的插槽,它将并行运行。如果在任务池中获取所有插槽,则可能会限制任务的执行,以避免CPU被淹没,并且可能无法同时执行任务:无法保证。

这是一个简化的解释,对调度策略的更完整和详细的解释是explained on the TaskScheduler documentation

作为旁注。 documentation for StartTask提到了StartNew(Action)Run(Action)之间的细微差别。与其他答案不同,它们并不完全等效。

  

从.NET Framework 4.5开始,您可以使用Task.Run(Action)方法作为使用默认参数调用StartNew(Action)的快速方法。但请注意,两种方法之间的行为存在差异:默认情况下,Task.Run(Action)不允许使用TaskCreationOptions.AttachedToParent选项启动的子任务连接到当前Task实例,而StartNew(Action)确实。

对于第二个问题

  

" P"在所有任务完成之后或完成之前设置?

简短的回答是肯定的。

但是,你应该考虑使用另一种方法,因为这会阻塞你的线程并等待空闲。另一种方法是,如果可以,则将控制权交还给调用者,因此线程被释放并可供CPU使用。如果运行此代码的线程是ThreadPool

的一部分,则尤其如此

因此,您应该更喜欢using WhenAll()。它返回一个可以等待的任务,或者可以调用ContinueWith的任务

示例:

var tasks = new Task[] {Task.Factory.StartNew(A), Task.Factory.StartNew(B), Task.Factory.StartNew(C)}; 
await Task.WhenAll(tasks);

答案 1 :(得分:2)

第一: 你正在以错误的方式创建任务。当你实例化一个任务时,你需要在它上面调用Start方法,否则它什么都没有。

new Task(() => /* Something * /).Start();

如果您按照刚才的方式创建任务(通过调用构造函数并按下启动或使用TaskFacotry甚至Task.Run),默认情况下ThreadPool线程将专用于该任务,因此任务将并行执行。 / p>

Task.WhenAll方法将阻止调用方法的执行,直到传递给它的所有任务都完成为止。

所以在完成所有任务后设置布尔变量。