多个等待与Task.WaitAll - 等效?

vid*_*oon 48 .net c# task-parallel-library async-await

在性能方面,会这2种方法运行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);
}
Run Code Online (Sandbox Code Playgroud)

===============方法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);
}
Run Code Online (Sandbox Code Playgroud)

=====================================

i3a*_*non 88

第一个选项不会同时执行这两个操作.它将执行第一个并等待其完成,然后才执行第二个.

第二个选项将同时执行,但会同步等待它们(即阻塞线程时).

您不应该同时使用这两个选项,因为第一个完成比第二个慢,第二个不需要阻塞线程.

您应该异步等待两个操作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);
}
Run Code Online (Sandbox Code Playgroud)

请注意,在Task.WhenAll完成两个任务之后,等待它们立即完成.

  • 你也可以完全跳过`await Task.WhenAll(getAllWidgetsTask,getAllFoosTask);`并等待任务(在等待第一个任务之前启动第二个任务). (6认同)
  • 谢谢。这就是我所需要的。“.Result”困扰着我,而您的回答避免了这种情况。 (2认同)
  • @kwesoly是正确的,但是只“暂停”一次会更有效率。 (2认同)
  • @StephenHolt 两者之间只有一个区别。`Result` 将任何异常包装在一个 `AggregateException` 中,然后您需要在所有错误处理代码中将其解开。`await` 为你打开它。除此之外,它们是相同的。 (2认同)

Nit*_*ram 15

简答:不.

Task.WaitAll阻塞,await一旦遇到任务就返回任务并注册函数的剩余部分并继续.

您正在寻找的"批量"等待方法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;
Run Code Online (Sandbox Code Playgroud)

这将使第一个示例与该Task.WhenAll方法非常相似.