Reputation: 5735
What is the difference when using await
on multiple await task vs waiting on all the tasks to finish. My under standing is the scenario 2 is better in terms of performance because both asyncTask1 and asyncTask2 are preformed in parallel.
scenario 1 :
async Task Task()
{
await asyncTask1();
await asyncTask2();
}
scenario 2 :
async Task Task()
{
t1 = asyncTask1();
t2 = asyncTask2();
await Task.WhenAll(createWorkflowtask, getTaskWorkflowTask);
}
Upvotes: 3
Views: 4331
Reputation: 30464
You wrote: "... because both asyncTask1 and asyncTask2 are preformed in parallel."
No they are not!
Addition: Below I wrote that everything in async-await is performed by one thread. Schneider commented correctly that in async-await multiple threads can be involved. See the addition at the end.
An article that helped me a lot to understand how async-await works was this interview with Eric-Lippert who compared async/await with a cook making dinner. (Somewhere half-way, search for async-await).
Eric Lippert explains that if a cook starts doing something and finds after a while that he has nothing else to do but wait for a process to finish, this cook looks around to see if he can do something else instead of waiting.
When using async/await, there is still one thread involved. This thread can do only one thing at a time. While the thread is busy doing Task1, it can't execute Task2. Only if it finds an await in Task1, it will start executing statements from Task2. In your scenario 2 the tasks are not executed in parallel.
However there is a difference between the scenarios. In scenario 1 the first statement of task2 will not be executed before task1 completely finishes. Scenario 2 will start executing the first statements of task2 as soon as task1 encounters an await.
If you really want task2 to do something while task1 is also doing something, you'll have to start doing task2 in a separate thread. The easy method to do this in your scenario would be:
var task1 = Task.Run( () => asyncTask1())
// this statement is executed while task1 begins executing on a different thread.
// hence this thread is free to do other things, like performing statements
// from task2:
var task2 = asyncTask();
// the following statement will only be executed if task2 encounters an await
DoSomethingElse();
// when we need results from both task1 and task2:
await Task.WhenAll(new Task[] {task1, task2});
So usually, it is best only to await for a task to finish if you need the result of this task. As long as you can do other things, do these other things, they will be executed as soon as the other task starts awaiting until you start awaiting, in which case your caller will start doing things until his await etc.
The advantage of this method above doing things in parallel are manyfold:
Addition: Schneider's comment below about several threads is correct.
Some testing showed me that the thread ID of the current thread in the awaitable tasks is different than the thread ID of the calling thread.
For newbees to async-await it is important to understand that although various threads are involved, async-await does NOT mean that the tasks are performed in parallel. If you want parallelism you specifically have to say that the task must be run in parallel.
It seems that the cook in Eric Lippert's analogy is in fact a team of cooks, who constantly look around to see if they can help some of the other cooks instead of waiting for their tasks to finish. And indeed if cook Albert sees an await and starts doing something else, cook Bernard might finish the task of cook Albert.
Upvotes: 4
Reputation: 2754
Using Task.WhenAll
WhenAll
methodFrom MSDN
If any of the supplied tasks completes in a faulted state, the returned task will also complete in a TaskStatus.Faulted state, where its exceptions will contain the aggregation of the set of unwrapped exceptions from each of the supplied tasks.
Using await
on multiple methods
You have control over sequences that functions called
You can use different return types and use that return types on next steps
Unhandled exception in one method will break the execution of other methods
Upvotes: 1
Reputation: 7973
In the first scenario you launch a task and then wait until is completed, then pass to the second one and wait until finish before exit from the method.
In the second scenario you launch the two task in parallel and then wait until tgey are completed when you call Task.WhenAll
Upvotes: 3
Reputation: 531
In scenario 1, tasks are run sequentially (asyncTask1 must complete before asyncTask2 starts) while in scenario 2 the two tasks can run in parallel.
Upvotes: 8