Task.WhenAll vs awaiting one by one

Read the explanation
What if

Each await finishes before the next line runs, so FetchAsync("b") starts only after a is done.

Predict first

Each FetchAsync waits 100 ms on the network. When does FetchAsync("b") start?

012345678910111213await FetchAsync("a")await FetchAsync("b")print a ba startsawait Task.Delaya endsb startsawait Task.Delayb ends

Tap any block to see what that thread is doing.

  • Waiting / parked
  • Running
  • Waiting on I/O
Step 1/4

Main awaits FetchAsync("a"). The next line doesn't run until it's done.

1public static async Task Main()2{3    string a = await FetchAsync("a");4    string b = await FetchAsync("b"); // starts only after a is done5    Console.WriteLine($"{a} {b}");6}7 8public static async Task<string> FetchAsync(string name)9{10    Console.WriteLine($"{name} starts");11    await Task.Delay(100); // a network call12    Console.WriteLine($"{name} ends");13    return name;14}

Explanation

What just happened

await FetchAsync("a") finished before the next line ran, so FetchAsync("b") started only after a was done. The two calls had nothing to do with each other, yet they ran in sequence: about 200 ms.

Try the what-if switch

Why

An async method starts the moment you call it. await is what makes the caller wait. Start everything first, then await them together.

Watch out

If one task throws, await Task.WhenAll(...) rethrows the first exception, but only after every task has finished.

Common questions

Does await run tasks in parallel?

No. await waits for that task before the next line runs, so two awaits in a row run one after the other.

Does Task.WhenAll start the tasks?

No. Calling an async method already starts it: it runs until its first await. Task.WhenAll only waits for tasks that are already running, and returns their results in the order you passed them.

Is Task.WhenAll parallel or concurrent?

For I/O like network calls, the waits overlap. For CPU work, use Task.Run for each piece so they can run on different threads.

Verified: this timeline matches a real program, checked in CI on .NET 8 and 10. How we verify. Unclear or wrong? Tell us