就性能而言,这两种方法是并行运行GetAllWidgets()
和GetAllFoos()
吗?
有没有理由使用一个而不是另一个?编译器幕后似乎发生了很多事情,所以我不清楚它。
=============方法A:使用多个等待======================
public async Task<IHttpActionResult> MethodA()
{
var customer = new Customer();
customer.Widgets = await _widgetService.GetAllWidgets();
customer.Foos = await _fooService.GetAllFoos();
return Ok(customer);
}
===============方法B:使用Task.WaitAll =====================
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
Task.WaitAll(new List[] {getAllWidgetsTask, getAllFoosTask});
customer.Widgets = getAllWidgetsTask.Result;
customer.Foos = getAllFoosTask.Result;
return Ok(customer);
}
=====================================
答案 0 :(得分:77)
第一个选项不会同时执行这两个操作。它将执行第一个并等待其完成,然后才执行第二个。
第二个选项将同时执行,但会同步等待它们(即阻塞线程时)。
您不应该同时使用这两个选项,因为第一个完成的速度比第二个慢,第二个阻止了一个不需要的线程。
您应该与Task.WhenAll
public async Task<IHttpActionResult> MethodB()
{
var customer = new Customer();
var getAllWidgetsTask = _widgetService.GetAllWidgets();
var getAllFoosTask = _fooService.GetAllFos();
await Task.WhenAll(getAllWidgetsTask, getAllFoosTask);
customer.Widgets = await getAllWidgetsTask;
customer.Foos = await getAllFoosTask;
return Ok(customer);
}
请注意,在Task.WhenAll
完成两项任务已完成后等待它们立即完成。
答案 1 :(得分:13)
简短回答:不。
Task.WaitAll
阻塞,await
在遇到任务后立即返回任务,并注册函数的剩余部分并继续。
&#34; bulk&#34;你正在寻找的等待方法是Task.WhenAll
,它实际上会创建一个新的Task
,当完成所有交给函数的任务时,它会完成。
像这样:await Task.WhenAll({getAllWidgetsTask, getAllFoosTask});
这是阻塞问题。
此外,您的第一个函数不会并行执行这两个函数。要使用await
,您必须写下这样的内容:
var widgetsTask = _widgetService.GetAllWidgets();
var foosTask = _fooService.GetAllWidgets();
customer.Widgets = await widgetsTask;
customer.Foos = await foosTask;
这将使第一个示例与Task.WhenAll
方法非常相似。
答案 2 :(得分:0)
只有你的第二个选项会同时运行它们。你的第一个将按顺序等待每个电话。
答案 3 :(得分:0)
一旦调用异步方法,它就会开始执行。它是否将在当前线程上执行(从而同步运行)或者它将运行异步无法确定。
因此,在您的第一个示例中,第一个方法将开始工作,但随后您使用await人为地停止代码流。因此,在第一个方法执行完毕之前,不会调用第二个方法。
第二个示例调用两个方法而不使用await停止流。因此,如果方法是异步的,它们将潜在并行运行。
答案 4 :(得分:0)
作为@ i3arnon所说的补充。您会看到,使用await
时,您不得不将封闭方法声明为async
,而使用waitAll
时则不必。那应该告诉你,除了主要答案所说的以外,还有更多的东西。在这里:
WaitAll
将阻塞,直到给定任务完成为止,在这些任务运行时,它不会将控制权传递回调用方。同样如前所述,任务是异步运行的,而不是调用方。
Await
不会阻塞调用者线程,但是它将暂停执行其下的代码,但是在任务运行时,控制权将返回给调用者。对于将控制权返回给调用者的事实(被调用的方法正在异步运行),您必须将该方法标记为异步。
希望区别很明显。干杯