Multiple awaits vs Task.WaitAll - equivalent?
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.
Introduction
Multiple await statements and Task.WaitAll are not equivalent. Sequential await calls execute tasks one after another, while Task.WhenAll (the async version of Task.WaitAll) runs tasks concurrently. Task.WaitAll blocks the calling thread synchronously and can cause deadlocks in UI and ASP.NET contexts. Use await Task.WhenAll() for concurrent async execution, and sequential await only when each task depends on the previous one's result.
Sequential Awaits (One at a Time)
Each await pauses until the task completes before starting the next:
Each call waits for the previous one to finish. Use this when tasks depend on each other (e.g., result1 is needed to start task2).
Task.WhenAll (Concurrent Async)
Start all tasks first, then await them together:
All three tasks start concurrently. Task.WhenAll completes when the slowest task finishes.
Getting Results from WhenAll
Task.WaitAll (Synchronous Block — Avoid)
Task.WaitAll blocks the calling thread until all tasks complete:
This is dangerous because it blocks the thread, which can cause deadlocks when the awaited tasks need the same synchronization context (common in WPF, WinForms, and older ASP.NET).
Side-by-Side Comparison
| Pattern | Concurrent | Async | Thread Blocked | Risk |
Sequential await | No | Yes | No | None |
await Task.WhenAll | Yes | Yes | No | None |
Task.WaitAll | Yes | No | Yes | Deadlock |
Task.WhenAny | Yes | Yes | No | None |
Error Handling
Task.WhenAny
Wait for the first task to complete:
Real-World Example
Common Pitfalls
- Assuming sequential
awaitandTask.WhenAllare equivalent: Sequential awaits run tasks one after another (total time = sum).Task.WhenAllruns them concurrently (total time = max). For independent tasks,WhenAllis significantly faster. - Using
Task.WaitAllinstead ofawait Task.WhenAll:WaitAllblocks the calling thread synchronously, which causes deadlocks in UI applications (WPF, WinForms) and legacy ASP.NET. Always useawait Task.WhenAllin async code. - Starting tasks inside the
awaitcall: Writingawait Task.WhenAll(await task1, await task2)awaits each task sequentially before passing results toWhenAll. Start tasks withoutawaitfirst, then pass theTaskobjects toWhenAll. - Not handling
AggregateExceptionfromTask.WhenAll: When multiple tasks inWhenAllfail, only the first exception is thrown byawait. To access all exceptions, inspecttask.Exception.InnerExceptionson theWhenAlltask. - Using
.Resultor.Wait()on an incomplete task: Accessing.Resulton a task that has not completed blocks the thread, just likeTask.WaitAll. Only access.Resultafterawait Task.WhenAllhas completed to ensure the tasks are finished.
Summary
- Sequential
awaitruns tasks one at a time — use when tasks depend on each other await Task.WhenAll()runs tasks concurrently — use for independent tasksTask.WaitAll()blocks the thread and risks deadlocks — avoid in async code- Start all tasks before awaiting to enable concurrency
- Use
Task.WhenAny()to get the result of the first task to complete
Related reading
- Multiple mutex locking strategies and why libraries don't use address comparison
- Multiple Spring Scheduled tasks simultaneously
- multiple tasks using python asyncio
- Multiplexing callbacks
- Multiple DbContext in .NET Aspire
- Multiple file-extensions searchPattern for System.IO.Directory.GetFiles
- multiprocess or threading in python?
- Multiprocessing causes Python to crash and gives an error may have been in progress in another thread when fork was called

OOD Fundamentals
Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
Interview Questions practice on Codemia
Over 8,000 real interview questions from top companies, searchable by company and role.