WaitAll vs WaitAny
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
WaitAll and WaitAny solve different coordination problems. WaitAll blocks until every task completes, while WaitAny blocks until at least one task completes. The right choice depends on whether your next step needs the whole batch or can proceed with the first available result.
WaitAll Means Full Barrier Synchronization
Use Task.WaitAll when the program cannot continue until every task in a set is done.
This acts like a barrier. The current thread is blocked until both tasks finish or until an exception or timeout path interrupts the wait.
WaitAny Means First Completion Wins
Use Task.WaitAny when any one completed task is enough to make progress.
The return value is the index of the completed task in the array you passed. The other tasks may still be running afterward.
Exception Behavior Is Different in Practice
With WaitAll, exceptions from faulted tasks are aggregated when the wait completes.
With WaitAny, the method only tells you that one task completed. That task may have completed successfully, faulted, or been canceled. You still need to inspect or await the completed task to observe its outcome.
Blocking Waits Are Often the Wrong Tool in Async Code
WaitAll and WaitAny are synchronous waiting APIs. They block the calling thread. In modern async .NET code, Task.WhenAll and Task.WhenAny are often better because they compose with await instead of blocking threads.
If you are already inside async application code, prefer the When... versions unless you specifically need blocking behavior.
Typical Use Cases
WaitAll fits workflows like:
- finishing several independent computations before building one final response
- waiting for a batch of file writes to complete
- synchronizing at the end of a parallel stage
WaitAny fits workflows like:
- racing redundant providers and taking the first healthy response
- consuming whichever worker finishes first
- reacting to the earliest signal in a monitoring loop
The right choice follows directly from the business rule.
Cancellation and Cleanup Still Matter
After WaitAny, the losing tasks keep running unless you cancel them. If you launch several redundant operations and only need one, add a CancellationToken strategy so the unused work does not continue burning resources.
With WaitAll, a single failure may still leave other tasks running until they finish or observe cancellation. Design the task bodies with cooperative cancellation if fast shutdown matters.
Common Pitfalls
A common mistake is using WaitAll inside UI threads or request threads, where blocking can freeze the app or reduce throughput. Another is assuming WaitAny cancels the remaining tasks automatically. It does not.
People also often ignore exception handling after WaitAny. The first completed task might be the first failure, not the first success.
Finally, in modern async code, blocking waits are often a sign that await Task.WhenAll or await Task.WhenAny would be the cleaner design.
Summary
- '
WaitAllblocks until every task completes.' - '
WaitAnyblocks until one task completes and returns its index.' - The two methods solve different coordination problems, not the same problem with different performance.
- In async .NET code,
Task.WhenAllandTask.WhenAnyare usually better than blocking waits. - Always plan for exceptions, cancellation, and the fate of unfinished tasks.

