Suppose you have the following code:
public class Person{
public static string GetName(){
return "John";
}
}
What do you suppose the different is between the following codes:
Console.WriteLine(Person.GetName());
And
string x = Person.GetName();
Console.WriteLine(x);
Hopefully you can see that it's essentially no difference; you'll see "John" in the console either way...
... and that's all your codes are doing; the FryEggsAsync method returns a Task, and whether you store that Task in a variable and then await the variable, or whether you immediately await the returned Task, you're still awaiting a Task returned by the method call
The only significant difference in storing the Task allows you to do some other stuff and then start awaiting the Task. If you're starting 10 tasks and stashing them in a list then Task.WhenAll'ing them that counts as "doing other stuff before you start awaiting".
On the notion that Task.WhenAll is doing some parallel things whereas await FryEggsAsync
isn't - I understand where the confusion is coming from but it's probably arising because you're doing this in the context of a console app which doesn't obviously do anything else while awaiting. If you had 3 five minute things to do to cook breakfast and you did them like:
await FryEggsAsync();
await MakeCoffeeAsync();
await BurnToastAsync();
Then sure, it takes 15 minutes to make breakfast if you wait for one thing to finish before you start the next.. but that's because you're only doing one thing at a time and the console app isn't doing anything else. If this was a windows GUI app with, say, a timer counting up how long breakfast was taking to make then you'd see a difference between calling FryEggs(); MakeCoffee(); BurnToast();
synchronously, and doing await FryEggsAsync(); await MakeCoffeeAsync(); await BurnToastAsync();
.
- In the sync version your timer would jam at 00:00 for 15 minutes and then suddenly jump to 15 minutes when all was done.
- If you awaited each call then the timer would tick up smoothly second by second while each thing was in progress, because awaiting allows the UI thread that started the FryEggsAsync to go back to what it should be doing; processing timer events, updating the UI, preventing windows from fading the window and marking it "Not responding". The whole process would still take 15 minutes because you aren't making the 3 components of breakfast at the same time, but the critical thing is that it would obviously be doing something "in parallel"; making breakfast and updating the timer label
(Note, I hesitate to use the word "parallel" because Async isn't parallel in the c# sense of the word; Async is 'freeing up a thread from waiting for a result, so it can go off and do other things'" so it achieves parallel in the English sense of the word ie "apparently doing things at the same time" but you shouldn't talk about "parallel" when using task-asyncronous pattern because c# parallel is another kind of "doing things at the same time"
About Task.WhenXx
The Task.WhenXx methods are helpers to deal with lists of tasks, and allow you to create points in the program where you will wait for some or all of multiple started tasks to complete.
When you start your 3 five minute breakfast tasks without an await, and collect them into a list, and then await Task.WhenAll
the list, you're awaiting a Task that completes when all 3 of the breakfast tasks complete.
They each proceed and take 5 minutes then all complete at roughly the same time, which then means the Task that's waiting for them all completes too, so your program hs paused while it waits for the 3 tasks to be worked on apparently simultaneously- but that doesn't mean that Task.When is the only way to achieve apparent simultaneity, it's just that in a console app you can't see anything else happening apparently simultaneously when you await the single FryEggs Task in your console app, but you can with Task.WhenAll
By starting 3 breakfast tasks that all output words to the console, and seeing them mix together you see "things happening simultaneously" but if you had also a code pattern like:
FryEggsAsync();
MakeCoffeeAsync();
BurnToastAsync();
await Task.Delay(TimeSpan.FromMinutes(9));
Then you would, for about 5 minutes, see the coffee and the toast and the frying mingling together, then they would finish after 5 minutes and your program would silently wait for another 4 minutes (the final await waits for 9 minutes) then carry on.
There is no Task.WhenAll there so it's not Task.WhenAll that achieves "doing things simultaneously", Task.WhenAll is just a mechanism for waiting as long as it takes for the slowest task in a list of tasks, to complete.