SyntaxStudy
Sign Up
C# CancellationToken and Timeouts
C# Beginner 1 min read

CancellationToken and Timeouts

`CancellationToken` is the standard mechanism for cooperative cancellation in .NET. A `CancellationTokenSource` creates a token; you pass the token to async methods. When you call `cts.Cancel()`, any method that is awaiting with that token will have an `OperationCanceledException` thrown at the next await point. Timeouts can be implemented by creating a `CancellationTokenSource` with a delay: `new CancellationTokenSource(TimeSpan.FromSeconds(30))`. Linking multiple sources together with `CancellationTokenSource.CreateLinkedTokenSource` lets you cancel on either condition — a user request or a timeout. Always check `ct.IsCancellationRequested` or call `ct.ThrowIfCancellationRequested()` at sensible intervals inside CPU-bound loops. Passing the token to `Task.Delay`, `HttpClient`, and database command methods ensures cancellation is propagated through the entire call chain.
Example
// CancellationToken, timeouts, and linked sources

// Simulate a long-running async task that respects cancellation
static async Task<string> ProcessDataAsync(
    int itemCount,
    CancellationToken ct = default)
{
    var results = new System.Text.StringBuilder();
    for (int i = 0; i < itemCount; i++)
    {
        ct.ThrowIfCancellationRequested(); // co-operative check

        // Simulate async work (e.g., DB call)
        await Task.Delay(100, ct);
        results.Append($"item-{i} ");
    }
    return results.ToString().TrimEnd();
}

// --- Example 1: manual cancellation ---
var cts = new CancellationTokenSource();

var task = ProcessDataAsync(20, cts.Token);
await Task.Delay(350);  // let it run for ~350 ms
cts.Cancel();

try
{
    string result = await task;
    Console.WriteLine($"Completed: {result}");
}
catch (OperationCanceledException)
{
    Console.WriteLine("Task was cancelled by the user.");
}

// --- Example 2: automatic timeout ---
using var timeoutCts = new CancellationTokenSource(TimeSpan.FromMilliseconds(250));
try
{
    string r = await ProcessDataAsync(10, timeoutCts.Token);
    Console.WriteLine(r);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Task timed out.");
}

// --- Example 3: linked sources (user cancel OR timeout) ---
using var userCts    = new CancellationTokenSource();
using var timeoutCts2 = new CancellationTokenSource(TimeSpan.FromSeconds(5));
using var linked = CancellationTokenSource
    .CreateLinkedTokenSource(userCts.Token, timeoutCts2.Token);

try
{
    await ProcessDataAsync(5, linked.Token);
    Console.WriteLine("Done.");
}
catch (OperationCanceledException)
{
    Console.WriteLine($"Cancelled. Timeout: {timeoutCts2.IsCancellationRequested}");
}