Timeouts in C#

Timeouts are important for programs that connect to external resources or that otherwise need to bound execution time. Implementing timeouts in C# is straightforward using the Task class and its WaitAsync method.

using System;
using System.Threading;
using System.Threading.Tasks;

class Program
{
    static async Task Main()
    {
        // For our example, suppose we're executing an external
        // call that returns its result after 2 seconds.
        var task1 = Task.Run(async () =>
        {
            await Task.Delay(2000);
            return "result 1";
        });

        // Here we implement a timeout using Task.WaitAsync.
        // If the task doesn't complete within 1 second, it will timeout.
        try
        {
            var result = await task1.WaitAsync(TimeSpan.FromSeconds(1));
            Console.WriteLine(result);
        }
        catch (TimeoutException)
        {
            Console.WriteLine("timeout 1");
        }

        // If we allow a longer timeout of 3 seconds, then the task
        // will complete and we'll print the result.
        var task2 = Task.Run(async () =>
        {
            await Task.Delay(2000);
            return "result 2";
        });

        try
        {
            var result = await task2.WaitAsync(TimeSpan.FromSeconds(3));
            Console.WriteLine(result);
        }
        catch (TimeoutException)
        {
            Console.WriteLine("timeout 2");
        }
    }
}

Running this program shows the first operation timing out and the second succeeding.

$ dotnet run
timeout 1
result 2

In this C# version, we use Task.Run to simulate long-running operations. The Task.Delay method is used to create a delay, similar to time.Sleep in the original example.

We implement timeouts using the Task.WaitAsync method, which allows us to specify a timeout duration. If the task doesn’t complete within the specified time, a TimeoutException is thrown.

The try-catch blocks are used to handle the timeout scenarios. If a TimeoutException is caught, we print the timeout message. Otherwise, the task completed successfully, and we print the result.

This approach provides a clean and idiomatic way to implement timeouts in C#, leveraging the language’s built-in asynchronous programming features.