C# Cancellation
Cancellation is a cooperative signal that asks running work to stop early. A CancellationTokenSource raises the signal and a CancellationToken carries it to the work.
A loop that cancels itself
The loop cancels its own source when the counter reaches a fixed value. The next token check throws into the catch block.
using System;
using System.Threading;
class Program
{
static void Main(string[] args)
{
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
try
{
for (int step = 1; step <= 5; step++)
{
if (step == 3)
{
source.Cancel();
}
token.ThrowIfCancellationRequested();
Console.WriteLine("Step " + step);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Stopped");
}
}
}A token cancelled before use
The source is cancelled before the token reaches Task.Delay. The await throws at once and the catch block runs.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main(string[] args)
{
CancellationTokenSource source = new CancellationTokenSource();
source.Cancel();
try
{
await Task.Delay(1000, source.Token);
Console.WriteLine("Finished");
}
catch (OperationCanceledException)
{
Console.WriteLine("Cancelled");
}
}
}Checking without throwing
The Work method reads IsCancellationRequested and returns early. The first call runs and the second call skips after Main cancels.
using System;
using System.Threading;
class Program
{
static void Work(CancellationToken token, string name)
{
if (token.IsCancellationRequested)
{
Console.WriteLine(name + " skipped");
return;
}
Console.WriteLine(name + " done");
}
static void Main(string[] args)
{
CancellationTokenSource source = new CancellationTokenSource();
Work(source.Token, "First");
source.Cancel();
Work(source.Token, "Second");
}
}Example
using System;
using System.Threading;
class Program
{
static void Main(string[] args)
{
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
string[] steps = { "Load", "Parse", "Save", "Print" };
try
{
for (int i = 0; i < steps.Length; i++)
{
if (i == 2)
{
source.Cancel();
}
token.ThrowIfCancellationRequested();
Console.WriteLine(steps[i]);
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Stopped early");
}
}
}Key points
- The using System.Threading line brings in CancellationTokenSource and CancellationToken.
- The source owns the signal and its Cancel method raises it.
- The token is the read-only view that workers receive and check.
- Cancellation is cooperative, so a worker stops only where it checks the token.
- ThrowIfCancellationRequested throws OperationCanceledException once the signal is raised.
- IsCancellationRequested reads the signal without throwing, for a graceful exit.
- A token cancelled before use makes a token-aware await stop at once.
In this example, a loop walks four named steps and checks the token before each one. The loop cancels its own source when the index reaches the third step. The token check throws and the catch block prints the stop line. Only the first two step names print.
Try it Yourself
Edit the code, then press Run.
Running is simulated
Exercise
Why is cancellation called cooperative?