DEV Community

Cover image for Task.WhenEach in .NET: Process Tasks as They Complete
Morteza Jangjoo
Morteza Jangjoo

Posted on

Task.WhenEach in .NET: Process Tasks as They Complete

When you work with asynchronous programming in .NET, you often deal with multiple tasks running in parallel. Traditionally, we use:

  • Task.WhenAll – waits for all tasks to finish.
  • Task.WhenAny – continues as soon as one task finishes.

But what if you want to process each task as it completes, without waiting for the slowest one?
Enter Task.WhenEach (introduced in .NET 6+).


Why Task.WhenEach?

Imagine calling several APIs with different response times. Using Task.WhenAll, you must wait for the slowest API before processing results.

Task.WhenEach allows you to:

  • Process results immediately as each task finishes.
  • Improve responsiveness in partial-result scenarios.
  • Reduce latency in real-time or streaming-like applications.

Examples

Using Task.WhenAll

var tasks = new[]
{
    Task.Delay(3000).ContinueWith(_ => "Task 1"),
    Task.Delay(1000).ContinueWith(_ => "Task 2"),
    Task.Delay(2000).ContinueWith(_ => "Task 3")
};

var results = await Task.WhenAll(tasks);
foreach (var result in results)
{
    Console.WriteLine($"Processed: {result}");
}
Enter fullscreen mode Exit fullscreen mode

Output order:

Processed: Task 1
Processed: Task 2
Processed: Task 3
Enter fullscreen mode Exit fullscreen mode

Even though Task 2 finished first, results are processed after all tasks complete.


Using Task.WhenEach

await foreach (var task in Task.WhenEach(tasks))
{
    Console.WriteLine($"Processed: {await task}");
}
Enter fullscreen mode Exit fullscreen mode

Output order:

Processed: Task 2
Processed: Task 3
Processed: Task 1
Enter fullscreen mode Exit fullscreen mode

Now, each result is processed as soon as its task finishes, giving you faster responsiveness.


Real-World Use Cases

  1. API Aggregation – Fetch multiple external APIs simultaneously.
  2. File Processing – Handle large files one by one.
  3. Web Crawling – Return partial results to users progressively.
  4. Streaming Scenarios – Act on data incrementally instead of waiting for all of it.

When to Use Which

  • Task.WhenAll – when all results are needed before proceeding.
  • Task.WhenAny – when you only care about the first completed task.
  • Task.WhenEach – when you want to process tasks progressively.

Conclusion

Task.WhenEach is a game-changer for asynchronous programming in .NET.
It helps write more responsive applications and handle tasks efficiently without waiting for the slowest operation.

If you haven’t tried it yet, start replacing some WhenAll scenarios with WhenEach and see the difference.


💡 Tip: Combine Task.WhenEach with async streams (await foreach) to build responsive APIs or real-time dashboards.


I’m Morteza Jangjoo and “Explaining things I wish someone had explained to me”

Top comments (0)