0
0
CsharpHow-ToBeginner · 3 min read

How to Use Task.WhenAny in C# for Efficient Task Handling

Use Task.WhenAny in C# to wait for the first task to complete among multiple tasks. It returns a task that completes when any of the supplied tasks finish, allowing you to process the fastest result without waiting for all tasks.
📐

Syntax

The Task.WhenAny method accepts a collection of tasks and returns a Task<Task> that completes when any one of the input tasks completes.

Key parts:

  • Task.WhenAny(params Task[] tasks): Accepts multiple tasks as parameters.
  • Returns a Task<Task> representing the first completed task.
  • You can await the returned task to get the completed task and then check its result or status.
csharp
Task<Task> WhenAny(params Task[] tasks);
💻

Example

This example shows how to start three tasks with different delays and use Task.WhenAny to await the first one that finishes. It then prints which task completed first.

csharp
using System;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        Task task1 = Task.Delay(3000); // 3 seconds
        Task task2 = Task.Delay(1000); // 1 second
        Task task3 = Task.Delay(2000); // 2 seconds

        Task<Task> firstFinishedTask = Task.WhenAny(task1, task2, task3);

        Task completed = await firstFinishedTask;

        if (completed == task1)
            Console.WriteLine("Task 1 finished first.");
        else if (completed == task2)
            Console.WriteLine("Task 2 finished first.");
        else if (completed == task3)
            Console.WriteLine("Task 3 finished first.");
    }
}
Output
Task 2 finished first.
⚠️

Common Pitfalls

Common mistakes when using Task.WhenAny include:

  • Not awaiting the returned task properly, which can cause the program to continue before any task completes.
  • Assuming the returned task is the result itself, but it actually returns the first completed task wrapped inside another task.
  • Not handling exceptions from the completed task, which can cause unobserved exceptions.

Always await Task.WhenAny and then check or await the returned completed task to handle results or exceptions.

csharp
/* Wrong way: Not awaiting Task.WhenAny */
var first = Task.WhenAny(task1, task2);
// This does not wait for any task to complete

/* Right way: Await Task.WhenAny and then the completed task */
var firstCompleted = await Task.WhenAny(task1, task2);
await firstCompleted; // To observe exceptions or get result if Task<T>
📊

Quick Reference

  • Purpose: Wait for the first task to complete among many.
  • Returns: A task that completes with the first finished task.
  • Use case: When you want to proceed as soon as any task finishes, not all.
  • Remember: Await the returned task, then handle the completed task.

Key Takeaways

Task.WhenAny waits for the first task to complete among multiple tasks.
It returns a Task that you must await to get the completed task.
Always await the completed task to handle results or exceptions properly.
Use Task.WhenAny to improve responsiveness by processing the fastest task.
Do not confuse Task.WhenAny with Task.WhenAll; they serve different purposes.