C# WhenAny

Summary: in this tutorial, you’ll learn how to use the C# WhenAny() static method of the Task class to create a task that will complete when any of the input tasks have been completed.

Introduction to the C# WhenAny() method

The Task.WhenAny() is a static method of the Task class that allows you to wait for the first task in a collection of tasks to complete.

When a task completes, the Task.WhenAny() returns a Task<T> object that represents the completed task.

To use the Task.WhenAny() method, you follow these steps:

  • First, pass a collection of tasks to the method.
  • Second, use the await keyword to wait for any of the tasks in the collection to complete.
  • Third, assign the completed task to a variable and use the await keyword again to get the result.

The C# WhenAny() method is useful when you have to make multiple HTTP requests to different APIs and process the first result.

For example, suppose you have an app that displays the latest news from multiple sources, each source has an API.

To display the news as soon as possible, you can use the Task.WhenAny() method to wait for the first API request to complete, display the news and continue fetching the news from other APIs in parallel.

A simple C# WhenAny() method example

The following example demonstrates how to use the WhenAny() method:

static async Task<int> DoWork(int number, int ms)
{
    await Task.Delay(ms);
    return number;
}

var t1 = Task.Run(() => DoWork(1, 1000));
var t2 = Task.Run(() => DoWork(2, 500));

Task<int> completedTask = await Task.WhenAny(t1, t2);
int result = await completedTask;

Console.WriteLine(result);Code language: JavaScript (javascript)

How it works.

First, define the DoWork() method that accepts two parameters: number, an integer, and ms, a number of milliseconds. The method returns the number after a delay of ms milliseconds:

static async Task<int> DoWork(int number, int ms)
{
    await Task.Delay(ms);
    return number;
}Code language: JavaScript (javascript)

Second, create two tasks t1 and t2 using the Task.Run() method. The tasks execute the DoWork() method with different parameters:

  • t1 call DoWork(1,1000) that delays for 1000 milliseconds before returning the number 1.
  • t2 call DoWork(2,500) that delays for 500 milliseconds before returning the number 2.
var t1 = Task.Run(() => DoWork(1, 1000));
var t2 = Task.Run(() => DoWork(2, 500));Code language: JavaScript (javascript)

Third, use the Task.WhenAny() method to wait for either t1 or t2 to complete, whichever finishes first. When one of the tasks completes, the Task.WhenAny() method returns a Task<int> object that represents the completed task.

Task<int> completedTask = await Task.WhenAny(t1, t2);
int result = await completedTask;Code language: JavaScript (javascript)

Fourth, use the await keyword to wait for the Task<int> object to complete and assign the result to completedTask variable:

int result = await completedTask;Code language: JavaScript (javascript)

Finally, output the result to the console:

Console.WriteLine(result);Code language: CSS (css)

Practical use of the C# WhenAny() method

The following program attempts to download two images from different URLs and saves the first one using the C# WhenAny() method:


// Define the URLs of the two images
string url1 = "https://via.placeholder.com/600/771796";
string url2 = "https://via.placeholder.com/600/24f355";

// Create two tasks to request the two images asynchronously
HttpClient client = new();

var t1 = client.GetByteArrayAsync(url1);
var t2 = client.GetByteArrayAsync(url2);

// Wait for the first task to complete
var completedTask = await Task.WhenAny(t1, t2);

// Save the result of the first task to a file
byte[] bytes = await completedTask;
string fileName = "image.jpg";
File.WriteAllBytes(fileName, bytes);

Console.WriteLine($"The picture has been saved to {fileName}");Code language: JavaScript (javascript)

How it works.

First, define the URLs of the two images to download:

string url1 = "https://via.placeholder.com/600/771796";
string url2 = "https://via.placeholder.com/600/24f355";Code language: JavaScript (javascript)

Second, create a new instance of the HttpClient class to make HTTP requests:

HttpClient client = new();Code language: C# (cs)

Third, create two tasks that download the two pictures asynchronously. The GetByteArrayAsync() method returns a Task<byte[]> object:

var t1 = client.GetByteArrayAsync(url1);
var t2 = client.GetByteArrayAsync(url2);Code language: C# (cs)

Fourth, use the Task.WhenAny() method to wait for the first task to complete:

var completedTask = await Task.WhenAny(t1, t2);Code language: C# (cs)

Finally, save the result of the first task into a file:

byte[] bytes = await completedTask;
string fileName = "image.jpg";
File.WriteAllBytes(fileName, bytes);

Console.WriteLine($"Saved the picture to {fileName}");Code language: C# (cs)

Summary

  • Use the C# WhenAny() method to wait for the first task in a collection of tasks to finish.
Was this tutorial helpful ?