Let’s go through Cancellation Tokens in C# β€” a standard way to cancel running tasks or asynchronous operations safely.


πŸ“Œ 1. What is a Cancellation Token?

  • CancellationToken allows cooperative cancellation of tasks or async operations.

  • Instead of forcefully killing a thread, the task checks periodically if it should cancel.

  • Works with:

    • Task / Task<T>

    • async / await

    • Parallel operations


πŸ“Œ 2. Creating a CancellationToken

using System;
using System.Threading;
using System.Threading.Tasks;
 
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
  • CancellationTokenSource β†’ controls the token

  • CancellationToken β†’ passed to tasks to observe cancellation


πŸ“Œ 3. Using CancellationToken in a Task

Task.Run(() =>
{
    for (int i = 0; i < 10; i++)
    {
        token.ThrowIfCancellationRequested(); // Check for cancellation
        Console.WriteLine($"Processing {i}");
        Thread.Sleep(500);
    }
}, token);
  • ThrowIfCancellationRequested() throws OperationCanceledException if cancelled

  • Task can then stop gracefully


πŸ“Œ 4. Cancelling a Task

cts.Cancel(); // Request cancellation
  • Task observes cancellation via token and stops execution

  • Wrap in try-catch to handle cancellation:

try
{
    await Task.Run(() =>
    {
        for (int i = 0; i < 10; i++)
        {
            token.ThrowIfCancellationRequested();
            Thread.Sleep(500);
        }
    }, token);
}
catch (OperationCanceledException)
{
    Console.WriteLine("Task was canceled!");
}

πŸ“Œ 5. Using CancellationToken with Async Methods

async Task DownloadFileAsync(string url, CancellationToken token)
{
    for (int i = 0; i < 10; i++)
    {
        token.ThrowIfCancellationRequested();
        await Task.Delay(500); // Simulate download
        Console.WriteLine($"Downloaded {i * 10}%");
    }
}
  • Pass token to async methods for cooperative cancellation

πŸ“Œ 6. Parallel Loops with CancellationToken

ParallelOptions options = new ParallelOptions
{
    CancellationToken = token
};
 
try
{
    Parallel.For(0, 10, options, i =>
    {
        Console.WriteLine(i);
        Thread.Sleep(200);
    });
}
catch (OperationCanceledException)
{
    Console.WriteLine("Parallel loop canceled!");
}
  • Supports cooperative cancellation in parallel loops

πŸ“Œ 7. Full Example

using System;
using System.Threading;
using System.Threading.Tasks;
 
class Program
{
    static async Task Main(string[] args)
    {
        // Create a cancellation token source
        CancellationTokenSource cts = new CancellationTokenSource();
 
        // Register a task to cancel after 3 seconds
        cts.CancelAfter(3000);
 
        try
        {
            Console.WriteLine("Starting long-running task...");
            int result = await LongRunningOperationAsync(cts.Token);
            Console.WriteLine($"Task completed successfully: {result}");
        }
        catch (OperationCanceledException)
        {
            Console.WriteLine("Task was canceled!");
        }
        finally
        {
            cts.Dispose();
        }
    }
 
    // Async method that supports cancellation
    static async Task<int> LongRunningOperationAsync(CancellationToken token)
    {
        int sum = 0;
 
        for (int i = 1; i <= 10; i++)
        {
            token.ThrowIfCancellationRequested(); // check for cancellation
 
            Console.WriteLine($"Processing {i}...");
            sum += i;
 
            await Task.Delay(1000); // simulate work
        }
 
        return sum;
    }
}

πŸ“Œ 8. How It Works

  1. Create a CancellationTokenSource β†’ produces a CancellationToken.

  2. Pass the token to a method that supports cancellation.

  3. Inside the method:

    • Periodically check token.IsCancellationRequested or

    • Call token.ThrowIfCancellationRequested() to stop and throw an OperationCanceledException.

  4. Cancel the task by calling cts.Cancel() or cts.CancelAfter(milliseconds).

  5. Handle the cancellation with a try-catch block.


πŸ“Œ 9. Output Example (if canceled after 3 seconds)

Starting long-running task...
Processing 1...
Processing 2...
Processing 3...
Task was canceled!
  • Notice it stops mid-loop when cancellation is requested.

βœ… Summary:

  • CancellationToken = signal to stop work.

  • CancellationTokenSource = triggers that signal.

  • ThrowIfCancellationRequested() = the typical way to stop a task cleanly.


πŸ“Œ 11. Best Practices

  1. Always pass the token to methods performing cancellable work.

  2. Use ThrowIfCancellationRequested() for clean exit.

  3. Wrap task execution in try-catch to handle OperationCanceledException.

  4. Use Dispose() on CancellationTokenSource when done.


πŸ“Œ 12. Summary Table

FeatureDescription
CancellationTokenSourceCreates and controls cancellation
CancellationTokenObserved by tasks to respond to cancellation
Cancel a taskcts.Cancel()
Check for cancellationtoken.ThrowIfCancellationRequested()
Async & Parallel supportWorks with async/await and Parallel loops
Best practiceCooperative, graceful cancellation

βœ… Tip:

  • Use CancellationToken whenever your task might take a long time or may need to be cancelled by the user.

  • Avoid killing threads; instead, let tasks cooperate for graceful exit.