In terms of performance, will these 2 methods run GetAllWidgets()
and GetAllFoos()
in parallel?
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 ======================
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 =====================
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);
}
=====================================
The first option will not execute the two operations concurrently. It will execute the first and await its completion, 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
:Note that after
Task.WhenAll
completed both tasks already completed so awaiting them completes immediately.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.
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.
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.The "bulk" waiting method you were looking for is
Task.WhenAll
that actually creates a newTask
that finishes when all tasks that were handed to the function are done.Like so:
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:This will make the first example to act very similar to the
Task.WhenAll
method.Only your second option will run them in parallel. Your first will wait on each call in sequence.