Assuming you want to get all three jobs done and none of them depend on the other, then use Task.WhenAll()
and/or await
each separately after you start them. You don't necessarily need to use both.
var task1 = Task1();
var task2 = Task2();
var task3 = Task3();
Asynchronous methods always start running synchronously. So when you call Task1()
, it will run until the first await
that acts on an incomplete Task
. That will be when it starts waiting for whatever I/O request you're making. At that point, Task1()
returns an incomplete Task
, and execution proceeds to the next line: running Task2()
, etc.
That makes the best use of resources since you use the time that you're waiting for a response in Task1()
to start the next request in Task2()
, etc.
If you use await Task.WhenAll
, the current thread is freed to do other work. The three tasks may very well resume on the current thread once they're done waiting (depending on a few things), one after the other, in whatever order their respective requests had finished. Once they're all done, execution will proceed to the next line after await Task.WhenAll
.
This:
var result1 = await task1;
var result2 = await task2;
var result3 = await task3;
is very similar as doing Task.WhenAll()
(since you already started the tasks earlier). But here you are capturing the results returned from each. If you need to use the results, then you should use this.
If you use Task.WhenAll()
before await task1
then you will be waiting for all three to complete before you start using the result from task1
. If you can use the result from task1
before the other tasks complete, then there is no need to use Task.WhenAll()
.
This:
var result1 = task1.Result;
var result2 = task2.Result;
var result3 = task3.Result;
will block the current thread until task1
is completed. That may very well deadlock if the task needs to resume in the current context. See here for an explanation why: Don't Block on Async Code