How to Cancel Async Operation in C# with CancellationToken
To cancel an async operation in C#, use a
CancellationToken passed to the async method and call Cancel() on its CancellationTokenSource. The async method should regularly check token.IsCancellationRequested or throw OperationCanceledException to stop execution cleanly.Syntax
Use a CancellationTokenSource to create a CancellationToken. Pass this token to your async method. Call Cancel() on the source to request cancellation.
CancellationTokenSource: Controls cancellation requests.CancellationToken: Passed to async methods to observe cancellation.Cancel(): Signals the cancellation request.
csharp
var cts = new CancellationTokenSource(); CancellationToken token = cts.Token; async Task MyAsyncMethod(CancellationToken token) { while (!token.IsCancellationRequested) { // Do work await Task.Delay(1000, token); } token.ThrowIfCancellationRequested(); } // To cancel: cts.Cancel();
Example
This example shows a simple async method that counts numbers every second. It stops counting when cancellation is requested.
csharp
using System; using System.Threading; using System.Threading.Tasks; class Program { static async Task CountAsync(CancellationToken token) { int count = 0; try { while (true) { token.ThrowIfCancellationRequested(); Console.WriteLine($"Count: {count++}"); await Task.Delay(1000, token); } } catch (OperationCanceledException) { Console.WriteLine("Counting canceled."); } } static async Task Main() { var cts = new CancellationTokenSource(); var countingTask = CountAsync(cts.Token); // Cancel after 3 seconds await Task.Delay(3000); cts.Cancel(); await countingTask; } }
Output
Count: 0
Count: 1
Count: 2
Counting canceled.
Common Pitfalls
Common mistakes when cancelling async operations include:
- Not passing the
CancellationTokento async methods orTask.Delay, so cancellation is ignored. - Not checking
token.IsCancellationRequestedor not throwingOperationCanceledException, which prevents clean cancellation. - Calling
Cancel()but not awaiting the async method, which can cause unobserved exceptions.
csharp
/* Wrong way: ignoring token */ async Task WrongAsync() { await Task.Delay(5000); // No token passed } /* Right way: pass token and check it */ async Task RightAsync(CancellationToken token) { await Task.Delay(5000, token); token.ThrowIfCancellationRequested(); }
Quick Reference
- Create
CancellationTokenSourceto control cancellation. - Pass
CancellationTokento async methods and cancellable APIs. - Check
token.IsCancellationRequestedor calltoken.ThrowIfCancellationRequested()inside async code. - Call
Cancel()on the source to request cancellation. - Await the async method to handle cancellation exceptions properly.
Key Takeaways
Use CancellationTokenSource and CancellationToken to enable cancellation in async methods.
Always pass the CancellationToken to cancellable async calls like Task.Delay.
Check for cancellation inside your async method and throw OperationCanceledException for clean exit.
Call Cancel() on the CancellationTokenSource to request cancellation.
Await the async task to properly handle cancellation and exceptions.