Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/.net/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 多个等待vs Task.WaitAll-等效?_C#_.net_Async Await_Task Parallel Library - Fatal编程技术网

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两者之间只有一个区别<代码>结果
将所有异常包装在一个
聚合异常
中,然后需要在所有错误处理代码中打开该异常<代码>等待
为您打开它。除此之外,它们是一样的。