C# Task.WhenAny — Complete Guide
In this tutorial, you'll learn about C# Task.WhenAny. We cover key concepts, practical examples, and best practices.
You send the same request to multiple servers and need the first response. Or you have a timeout and a long operation — whichever finishes first wins. Task.WhenAny returns the first task to complete, letting you act on it immediately.
Wrong
var result = await FetchPrimaryAsync(); // Takes 5 seconds
// Even if a faster replica would respond in 1 second, we wait for the primary.
Output: Waits 5 seconds for the primary, ignoring faster alternatives.
Right
var primaryTask = FetchPrimaryAsync();
var secondaryTask = FetchSecondaryAsync();
var completedTask = await Task.WhenAny(primaryTask, secondaryTask);
var result = await completedTask; // First response wins
// Cancel the slower one
// (requires passing CancellationToken to both)
Output: Takes ~1 second instead of 5. The first server to respond provides the result.
Timeout pattern:
var workTask = LongOperationAsync(ct);
var timeoutTask = Task.Delay(5000, ct);
var completed = await Task.WhenAny(workTask, timeoutTask);
if (completed == timeoutTask)
{
throw new TimeoutException("Operation timed out");
}
return await workTask;
Prevention
- Use
Task.WhenAnyfor race conditions between multiple data sources. - Use
Task.WhenAnyfor timeout patterns (combine withTask.Delay). - Always
awaitthe completed task afterWhenAnyreturns — it may have faulted. - Cancel the slower tasks after
WhenAny— otherwise they continue running. - Use
Task.WhenAnywith a cancellation token to avoid resource leaks. - Do not use
Task.WhenAnywhen you need all results — useTask.WhenAll.
Common Mistakes with task when any
- Overlapping type class instances that cause GHC to reject the program with ambiguous dispatch errors
- Non-exhaustive pattern matches that compile with warnings then crash at runtime
- Misunderstanding that
Stringis[Char]with poor performance for large text operations
These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.
Practice Exercise
Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.
This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.
FAQ
Task.WhenAny is used in Doda Browser for replica selection — contacting multiple mirrors and using the first response. For more C# async, visit DodaTech.
Built by the developers of DodaTech
Doda Browser, DodaZIP & Durga Antivirus Pro