C# 在异步MVC web应用程序中寻找关于Task.WhenAll和wait的澄清

C# 在异步MVC web应用程序中寻找关于Task.WhenAll和wait的澄清,c#,asp.net,asp.net-mvc,asynchronous,C#,Asp.net,Asp.net Mvc,Asynchronous,我一直在研究如何将异步方法合并到我的MVC控制器中,特别是利用并行执行的潜力 我觉得特别有用。不过,有一个概念我希望澄清一下。上面我链接的文章使用以下代码并行执行一系列I/O绑定方法: var widgetTask = widgetService.GetWidgetsAsync(); var prodTask = prodService.GetProductsAsync(); var gizmoTask = gizmoService.GetGizmosAsync(); await Task.W

我一直在研究如何将异步方法合并到我的MVC控制器中,特别是利用并行执行的潜力

我觉得特别有用。不过,有一个概念我希望澄清一下。上面我链接的文章使用以下代码并行执行一系列I/O绑定方法:

var widgetTask = widgetService.GetWidgetsAsync();
var prodTask = prodService.GetProductsAsync();
var gizmoTask = gizmoService.GetGizmosAsync();

await Task.WhenAll(widgetTask, prodTask, gizmoTask);

var pwgVM = new ProdGizWidgetVM(
   widgetTask.Result,
   prodTask.Result,
   gizmoTask.Result
   );
我想知道的是,这与以下代码有何不同:

var widgetTask = widgetService.GetWidgetsAsync();
var prodTask = prodService.GetProductsAsync();
var gizmoTask = gizmoService.GetGizmosAsync();

var pwgVM = new ProdGizWidgetVM(
   await widgetTask,
   await prodTask,
   await gizmoTask
   );

据我所知,这两个代码块是等效的。对吗?如果没有,如果有人能解释差异,并建议我的情况下哪个更好,那就太好了。

1将并行执行所有3项任务,但不一定按顺序执行。

Task.whalll
完成时,内部的所有任务都已完成
widgetTask
将执行到它的第一个等待,然后在异步等待io绑定工作时,
prodTask
将执行到它的第一个等待,而在仍然等待前两个任务完成时,
GizmotTask
将执行到它的第一个等待。然后,在所有3个并行完成io绑定工作后,它们将运行到完成。在此之后,
任务。whalll
也将报告完成情况

2将以给定顺序并行执行所有3项任务

widgetask
将启动,然后
prodTask
将启动,然后
gizmoTask
。您开始等待
widgetTask
。完成后,它将返回并运行此任务中的非io绑定代码。完成后,将等待
prodTask
。由于它的io绑定工作是异步的,它可能已经完成了,所以这将非常快。io绑定工作完成后,将调用
prodTask
中的wait之后编码。同样适用于
gizmoTask


因此,只要您不关心任务内部等待后代码的执行顺序,通常您需要版本1而不是版本2。

1将并行执行所有3个任务,但不一定按顺序执行。

Task.whalll
完成时,内部的所有任务都已完成
widgetTask
将执行到它的第一个等待,然后在异步等待io绑定工作时,
prodTask
将执行到它的第一个等待,而在仍然等待前两个任务完成时,
GizmotTask
将执行到它的第一个等待。然后,在所有3个并行完成io绑定工作后,它们将运行到完成。在此之后,
任务。whalll
也将报告完成情况

2将以给定顺序并行执行所有3项任务

widgetask
将启动,然后
prodTask
将启动,然后
gizmoTask
。您开始等待
widgetTask
。完成后,它将返回并运行此任务中的非io绑定代码。完成后,将等待
prodTask
。由于它的io绑定工作是异步的,它可能已经完成了,所以这将非常快。io绑定工作完成后,将调用
prodTask
中的wait之后编码。同样适用于
gizmoTask


因此,只要您不关心任务中等待后的代码执行顺序,通常您需要的是版本1而不是版本2。

第一个代码片段等待所有任务完成。第二种方法是按顺序等待它们,这不是最容易维护的代码。想象一下,例如在所有任务完成后尝试添加一个断点,以便检查其结果。1是琐碎的,2是不可能的。对了,我明白你关于调试的观点。这是我没有考虑的一个重要问题。但就我的理解而言,我说在#2中,这些方法仍然是并行执行的,对吗?在这种情况下,按顺序等待结果并不重要,因为我只能在所有操作完成后继续操作。
wait
不会影响执行。当您调用异步方法时,任务开始执行<代码>等待仅影响异步等待。仅从这个意义上讲,这两个片段是等效的。但这可能仍然很重要,因为编译器必须为等待生成一个三步状态机,而不是一步状态机。编译器可能足够聪明,可以优化第二个代码段,并将其替换为
wait Task。虽然所有的
,但我怀疑第一个代码段是否会等待所有任务完成。第二种方法是按顺序等待它们,这不是最容易维护的代码。想象一下,例如在所有任务完成后尝试添加一个断点,以便检查其结果。1是琐碎的,2是不可能的。对了,我明白你关于调试的观点。这是我没有考虑的一个重要问题。但就我的理解而言,我说在#2中,这些方法仍然是并行执行的,对吗?在这种情况下,按顺序等待结果并不重要,因为我只能在所有操作完成后继续操作。
wait
不会影响执行。当您调用异步方法时,任务开始执行<代码>等待
仅影响异步等待。仅从这个意义上讲,这两个片段是等效的。但这可能仍然很重要,因为编译器必须为等待生成一个三步状态机,而不是一步状态机。编译器可能足够聪明,可以优化第二个代码段,并将其替换为
等待任务。在
任务中等待全部3个。等待全部或单独等待不会改变这一点。现在,如果
在调用
GetWidgetsAsync