In terms of performance, will these 2 methods run GetAllWidgets()
and GetAllFoos()
in parallel?
在性能方面,这两种方法是否会并行运行GetAllWidgets()和GetAllFoos()?
Is there any reason to use one over the other? There seems to be a lot happening behind the scenes with the compiler so I don't find it clear.
有没有理由使用一个而不是另一个?在编译器的幕后似乎发生了很多事情,所以我发现它并不清楚。
============= MethodA: Using multiple awaits ======================
=============方法A:使用多个等待======================
public async Task<IHttpActionResult> MethodA()
{
var customer = new Customer();
customer.Widgets = await _widgetService.GetAllWidgets();
customer.Foos = await _fooService.GetAllFoos();
return Ok(customer);
}
=============== MethodB: Using Task.WaitAll =====================
===============方法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);
}
=====================================
=====================================
4 个解决方案
#1
49
The first option will not execute the two operations concurrently. It will execute the first and await its comnpletion, and only then the second.
第一个选项不会同时执行这两个操作。它将执行第一个并等待它的同步,然后才执行第二个。
The second option will execute both concurrently but will wait for them synchronously (i.e. while blocking a thread).
第二个选项将同时执行,但将同步等待它们(即在阻塞线程时)。
You shouldn't use both options since the first completes slower than the second and the second blocks a thread without need.
您不应该同时使用这两个选项,因为第一个完成比第二个慢,第二个不需要阻塞线程。
You should wait for both operations asynchronously with Task.WhenAll
:
您应该与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);
}
Note that after Task.WhenAll
completed both tasks already completed so awaiting them completes immediately.
请注意,在Task.WhenAll完成两个已完成的任务之后,等待它们立即完成。
#2
7
Short answer: No.
简答:没有。
Task.WaitAll
is blocking, await
returns the task as soon as it is encountered and registers the remaining part of the function and continuation.
Task.WaitAll正在阻塞,await在遇到任务后立即返回该任务并注册该函数的剩余部分并继续。
The "bulk" waiting method you were looking for is Task.WhenAll
that actually creates a new Task
that finishes when all tasks that were handed to the function are done.
您正在寻找的“批量”等待方法是Task.WhenAll,它实际上创建了一个新任务,当完成所有传递给该功能的任务时,该任务完成。
Like so: await Task.WhenAll({getAllWidgetsTask, getAllFoosTask});
像这样:await Task.WhenAll({getAllWidgetsTask,getAllFoosTask});
That is for the blocking matter.
这是阻塞问题。
Also your first function does not execute both functions parallel. To get this working with await
you'd have to write something like this:
您的第一个函数也不会并行执行这两个函数。为了让这个工作等待你必须写这样的东西:
var widgetsTask = _widgetService.GetAllWidgets();
var foosTask = _fooService.GetAllWidgets();
customer.Widgets = await widgetsTask;
customer.Foos = await foosTask;
This will make the first example to act very similar to the Task.WhenAll
method.
这将使第一个示例与Task.WhenAll方法非常相似。
#3
0
Only your second option will run them in parallel. Your first will wait on each call in sequence.
只有您的第二个选项将并行运行它们。你的第一个将按顺序等待每个电话。
#4
0
As soon as you invoke the async method it will start executing. Whether it will execute on the current thread (and thus run synchronously) or it will run async is not possible to determine.
一旦调用异步方法,它就会开始执行。它是否将在当前线程上执行(因此同步运行)或者它将运行异步无法确定。
Thus, in your first example the first method will start doing work, but then you artificially stops the flow of the code with the await. And thus the second method will not be invoked before the first is done executing.
因此,在第一个示例中,第一个方法将开始工作,但随后您使用await人为地停止代码流。因此,在第一个方法完成执行之前,不会调用第二个方法。
The second example invokes both methods without stopping the flow with an await. Thus they will potentially run in parallel if the methods are asynchronous.
第二个示例调用这两个方法而不使用await停止流。因此,如果方法是异步的,它们可能会并行运行。
#1
49
The first option will not execute the two operations concurrently. It will execute the first and await its comnpletion, and only then the second.
第一个选项不会同时执行这两个操作。它将执行第一个并等待它的同步,然后才执行第二个。
The second option will execute both concurrently but will wait for them synchronously (i.e. while blocking a thread).
第二个选项将同时执行,但将同步等待它们(即在阻塞线程时)。
You shouldn't use both options since the first completes slower than the second and the second blocks a thread without need.
您不应该同时使用这两个选项,因为第一个完成比第二个慢,第二个不需要阻塞线程。
You should wait for both operations asynchronously with Task.WhenAll
:
您应该与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);
}
Note that after Task.WhenAll
completed both tasks already completed so awaiting them completes immediately.
请注意,在Task.WhenAll完成两个已完成的任务之后,等待它们立即完成。
#2
7
Short answer: No.
简答:没有。
Task.WaitAll
is blocking, await
returns the task as soon as it is encountered and registers the remaining part of the function and continuation.
Task.WaitAll正在阻塞,await在遇到任务后立即返回该任务并注册该函数的剩余部分并继续。
The "bulk" waiting method you were looking for is Task.WhenAll
that actually creates a new Task
that finishes when all tasks that were handed to the function are done.
您正在寻找的“批量”等待方法是Task.WhenAll,它实际上创建了一个新任务,当完成所有传递给该功能的任务时,该任务完成。
Like so: await Task.WhenAll({getAllWidgetsTask, getAllFoosTask});
像这样:await Task.WhenAll({getAllWidgetsTask,getAllFoosTask});
That is for the blocking matter.
这是阻塞问题。
Also your first function does not execute both functions parallel. To get this working with await
you'd have to write something like this:
您的第一个函数也不会并行执行这两个函数。为了让这个工作等待你必须写这样的东西:
var widgetsTask = _widgetService.GetAllWidgets();
var foosTask = _fooService.GetAllWidgets();
customer.Widgets = await widgetsTask;
customer.Foos = await foosTask;
This will make the first example to act very similar to the Task.WhenAll
method.
这将使第一个示例与Task.WhenAll方法非常相似。
#3
0
Only your second option will run them in parallel. Your first will wait on each call in sequence.
只有您的第二个选项将并行运行它们。你的第一个将按顺序等待每个电话。
#4
0
As soon as you invoke the async method it will start executing. Whether it will execute on the current thread (and thus run synchronously) or it will run async is not possible to determine.
一旦调用异步方法,它就会开始执行。它是否将在当前线程上执行(因此同步运行)或者它将运行异步无法确定。
Thus, in your first example the first method will start doing work, but then you artificially stops the flow of the code with the await. And thus the second method will not be invoked before the first is done executing.
因此,在第一个示例中,第一个方法将开始工作,但随后您使用await人为地停止代码流。因此,在第一个方法完成执行之前,不会调用第二个方法。
The second example invokes both methods without stopping the flow with an await. Thus they will potentially run in parallel if the methods are asynchronous.
第二个示例调用这两个方法而不使用await停止流。因此,如果方法是异步的,它们可能会并行运行。