C# 多个等待vs Task.WaitAll-等效?
就性能而言,这两个方法是否会并行运行C# 多个等待vs Task.WaitAll-等效?,c#,.net,async-await,task-parallel-library,C#,.net,Async Await,Task Parallel Library,就性能而言,这两个方法是否会并行运行GetAllWidgets()和GetAllFoos() 有什么理由用一个代替另一个吗?编译器的幕后似乎发生了很多事情,所以我不太清楚 ============方法A:使用多个等待====================== public async Task<IHttpActionResult> MethodA() { var customer = new Customer(); customer.Widgets = await
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);
}
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);
}
public async Task MethodA()
{
var customer=新客户();
customer.Widgets=wait_widgetService.GetAllWidgets();
customer.Foos=wait_fooService.GetAllFoos();
返回Ok(客户);
}
===============方法B:使用Task.WaitAll=====================
public async Task<IHttpActionResult> MethodA()
{
var customer = new Customer();
customer.Widgets = await _widgetService.GetAllWidgets();
customer.Foos = await _fooService.GetAllFoos();
return Ok(customer);
}
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);
}
公共异步任务方法b()
{
var customer=新客户();
var getAllWidgetsTask=_widgetService.GetAllWidgets();
var getAllFoosTask=_fooService.GetAllFos();
Task.WaitAll(新列表[]{getAllWidgetsTask,getAllFoosTask});
customer.Widgets=getAllWidgetsTask.Result;
customer.Foos=getAllFoosTask.Result;
返回Ok(客户);
}
============================================只有第二个选项将并行运行它们。第一个将按顺序等待每个调用。一旦调用异步方法,它将开始执行。无法确定它是在当前线程上执行(从而同步运行)还是异步运行
public async Task<IHttpActionResult> MethodA()
{
var customer = new Customer();
customer.Widgets = await _widgetService.GetAllWidgets();
customer.Foos = await _fooService.GetAllFoos();
return Ok(customer);
}
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);
}
因此,在您的第一个示例中,第一个方法将开始工作,但随后您使用wait人工停止代码流。因此,在执行第一个方法之前,不会调用第二个方法
第二个示例调用这两个方法,而不使用wait停止流。因此,如果这些方法是异步的,它们可能会并行运行 第一个选项不会同时执行这两个操作。它将执行第一个并等待其完成,然后才执行第二个 第二个选项将同时执行这两个选项,但将同步等待它们(即在阻塞线程时) 您不应该同时使用这两个选项,因为第一个选项的完成速度比第二个慢,而第二个选项不需要阻塞线程 您应该使用
任务异步等待这两个操作。当所有:
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);
}
公共异步任务方法b()
{
var customer=新客户();
var getAllWidgetsTask=_widgetService.GetAllWidgets();
var getAllFoosTask=_fooService.GetAllFos();
等待任务时(getAllWidgetsTask,getAllFoosTask);
customer.Widgets=await getAllWidgetsTask;
customer.Foos=等待getAllFoosTask;
返回Ok(客户);
}
请注意,在任务之后。当所有的任务都完成时,两个任务都已经完成,因此等待它们的任务将立即完成。简短回答:否
Task.WaitAll
正在阻塞,wait
在遇到任务时立即返回该任务,并注册函数的剩余部分和continuation
您正在寻找的“批量”等待方法是Task.whalll
,它实际上创建了一个新的Task
,在交给函数的所有任务完成时完成
类似这样:wait Task.WhenAll({getAllWidgetsTask,getAllFoosTask})代码>
这就是阻碍问题
此外,您的第一个函数不会同时执行两个函数。要使用wait
实现此功能,您必须编写如下内容:
var widgetsTask = _widgetService.GetAllWidgets();
var foosTask = _fooService.GetAllWidgets();
customer.Widgets = await widgetsTask;
customer.Foos = await foosTask;
这将使第一个示例与任务.whalll
方法非常相似。作为@i3arnon所说内容的补充。您将看到,当您使用wait
时,您被迫将封闭方法声明为async
,但使用waitAll
时,您不会这样做。这应该告诉你,这比主要答案所说的要多得多。这是:
WaitAll
将阻塞,直到给定任务完成,在这些任务运行时,它不会将控制权传递回调用方。同样如前所述,任务对其自身而不是对调用方异步运行
wait
不会阻止调用方线程,但会暂停其下代码的执行,但在任务运行时,控制权会返回给调用方。由于控件返回给调用方(被调用的方法运行异步),因此必须将该方法标记为异步
希望差别是明显的。干杯在第一个示例中,这两个方法将按顺序调用,而在第二个示例中,它们将并行运行,因此它们并不等效。另外,在第二个方法中,您在执行任务时正在阻塞。只有当\u widgetService.GetAllWidgets()
完成时,MethodA才会执行\u fooService.GetAllFoos()
,当\u fooService.GetAllFoos()
中未完成的任务返回时,methodB才会执行它。谢谢。这就是我需要的。“.Result”困扰着我,你的回答避免了这一点。你也可以完全跳过wait Task.WhenAll(getAllWidgetsTask,getAllFoosTask)
和just Wait tasks(在等待第一个任务之前只启动第二个任务)。@kwesoly这是对的,但只“暂停”一次会更有效一些。@i3arnon-听起来是个很好的理由,仅仅为了等待而切换上下文是没有意义的。@StephenHolt两者之间只有一个区别<代码>结果
将所有异常包装在一个聚合异常
中,然后需要在所有错误处理代码中打开该异常<代码>等待
为您打开它。除此之外,它们是一样的。