Cancellation with CancellationToken
Long-running async work should be cancellable, a user closes a dialog, navigates away, or a timeout expires. CancellationToken is the standard way to signal that.
using System;
using System.Threading;
using System.Threading.Tasks;
class Program
{
static async Task Main()
{
using var cts = new CancellationTokenSource();
cts.CancelAfter(TimeSpan.FromSeconds(3));
try
{
await CountAsync(cts.Token);
}
catch (OperationCanceledException)
{
Console.WriteLine("Cancelled!");
}
}
static async Task CountAsync(CancellationToken token)
{
for (int i = 1; i <= 10; i++)
{
token.ThrowIfCancellationRequested();
Console.WriteLine(i);
await Task.Delay(1000, token);
}
}
}
The pieces
CancellationTokenSourceis the object that can trigger cancellation,cts.Cancel()cancels immediately,cts.CancelAfter(...)schedules it.CancellationToken(fromcts.Token) is the read-only signal you pass down into async methods, they check it, they can't cancel anything themselves.token.ThrowIfCancellationRequested()throws anOperationCanceledExceptionif cancellation was requested, stopping the method's work at a clean point instead of continuing pointlessly.- Passing the token into
Task.Delay(1000, token)lets the delay itself respond to cancellation immediately, instead of finishing its full second first.
Convention
Any async method that might run for a while should accept an optional CancellationToken token = default parameter and pass it through to everything it awaits, this makes cancellation flow all the way down a chain of async calls instead of only stopping the top-level one.