Skip to content

C# CancellationToken — Complete Guide

DodaTech Updated 2026-06-24 2 min read

In this tutorial, you'll learn about C# CancellationToken. We cover key concepts, practical examples, and best practices.

A long-running operation is no longer needed — the user navigated away, the request timed out, or a newer request replaced it. The operation continues consuming resources because nothing told it to stop. CancellationToken provides cooperative cancellation for async operations.

Wrong

public async Task<string> FetchDataAsync()
{
    // No cancellation support — always runs to completion
    using var response = await httpClient.GetAsync(url);
    return await response.Content.ReadAsStringAsync();
}

Output: The method runs to completion even if the result is no longer needed. Wastes resources.

public async Task<string> FetchDataAsync(CancellationToken ct = default)
{
    using var response = await httpClient.GetAsync(url, ct);
    ct.ThrowIfCancellationRequested();
    return await response.Content.ReadAsStringAsync(ct);
}

// Usage with timeout
using var cts = new CancellationTokenSource(TimeSpan.FromSeconds(5));
try
{
    var data = await FetchDataAsync(cts.Token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Request timed out");
}

Output: If cancelled, the operation stops promptly and throws OperationCanceledException.

Prevention

  • Pass CancellationToken to all async methods that perform I/O.
  • Provide a default parameter value so callers are not forced to pass one.
  • Use CancellationTokenSource to create tokens with timeout or manual cancellation.
  • Use ThrowIfCancellationRequested() to check cancellation at safe points.
  • Use Register() for callback-style cancellation notification.
  • Use ct.ThrowIfCancellationRequested() rather than checking ct.IsCancellationRequested and throwing — it is the standard pattern.
  • Never cancel with Thread.Abort() — always use cooperative cancellation.

Common Mistakes with cancellation token

  1. Forgetting deriving (Show, Eq) on custom data types needed for debugging
  2. Placing the wildcard pattern first in case expressions, making all subsequent patterns unreachable
  3. Using head and tail instead of pattern matching, causing runtime errors on empty lists

These mistakes appear frequently in real-world CSHARP code. DodaTech's contributors have identified these patterns through analysis of open-source projects and production systems.

Practice Exercise

Write a pure function that safely divides two integers using Maybe, then test it with edge cases like division by zero and negative numbers.

This exercise reinforces the concepts covered in this guide. Try implementing it before checking online solutions.

FAQ

How do I cancel after a timeout?

Create CancellationTokenSource with a timespan: new CancellationTokenSource(TimeSpan.FromSeconds(30)). The token cancels automatically after 30 seconds. Alternatively, call cts.CancelAfter(TimeSpan.FromSeconds(30)) on an existing source.

Can cancellation be ignored?

Yes. Cancellation is cooperative — the operation must check the token. If the operation never checks ct.IsCancellationRequested or calls ThrowIfCancellationRequested, cancellation has no effect. Always place checks at await points and in long-running loops.

What is the difference between OperationCanceledException and TaskCanceledException?

OperationCanceledException is the base. TaskCanceledException inherits from it and is thrown when a Task is cancelled before completion. Catch OperationCanceledException to handle both cases.

Cancellation tokens are critical in Doda Browser's page load pipeline — cancelling requests when users navigate away. For more C# async, visit DodaTech.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro