Explain the difference between `Task.WhenAll()` and `Task.WhenAny()`
4 minintermediate.NETasync-awaitTaskconcurrency
Quick Answer
`Task.WhenAll()` returns a task that completes when *all* supplied tasks finish (aggregating results and exceptions), so it's used to run independent operations concurrently and wait for every one. `Task.WhenAny()` completes as soon as *any* one task finishes, returning that task — useful for timeouts, first-response-wins, or redundancy. Both are non-blocking and awaitable.
Detailed Answer
Task.WhenAll() waits for all tasks in a collection to complete before continuing. It returns a task that completes when all input tasks have completed.
Key characteristics of Task.WhenAll():
- Waits for ALL tasks to finish
- Returns an array of results (if tasks return values)
- If any task throws an exception, the returned task will be faulted
- All exceptions are aggregated in an AggregateException
- Useful for parallel execution where you need all results
// Example: Download multiple files concurrently
var task1 = DownloadFileAsync("file1.txt");
var task2 = DownloadFileAsync("file2.txt");
var task3 = DownloadFileAsync("file3.txt");
// Wait for all downloads to complete
await Task.WhenAll(task1, task2, task3);
Console.WriteLine("All files downloaded");
Task.WhenAny() returns as soon as ANY one of the tasks completes. It returns a task that represents the first completed task.
Key characteristics of Task.WhenAny():
- Returns when the FIRST task completes
- Returns the completed task itself (not the result)
- Useful for timeout scenarios or racing multiple operations
- Other tasks continue running in the background
// Example: Implement timeout pattern
var dataTask = FetchDataAsync();
var timeoutTask = Task.Delay(TimeSpan.FromSeconds(5));
var completedTask = await Task.WhenAny(dataTask, timeoutTask);
if (completedTask == timeoutTask)
{
throw new TimeoutException("Operation timed out");
}
var result = await dataTask;