Have you come across any scenario where you started long-running asynchronous tasks in C# but want to cancel in the middle of the execution?
Either the user wants to cancel or the application itself is required to cancel the operation, it is a good idea to cancel the resource-heavy long-running operations (logic built using a database, report generation, etc.) gracefully.
Let's discuss about cancellation token in c# which is responsible for canceling tasks.
What is the Cancellation token in C#?
A cancellation token in C# is represented by the CancellationToken
struct is a way to notify an operation or task that should be cancelled cooperatively.
A CancellationToken
enables cooperative cancellation between threads, thread pool work items, or Task objects.
Why do you need a Cancellation token?
To enable cooperative cancellation of tasks/operations that might be no longer needed or take a long time to complete.
Cooperative cancellation means that the operation can check the cancellation token periodically and gracefully stop if it has been canceled, rather than being aborted abruptly.
This allows the operation to release any resources, close any files, or perform any other cleanup before exiting.
How to create a cancellation token in C#?
You can create a cancellation token by using a CancellationTokenSource
object, which manages the cancellation tokens retrieved from its CancellationTokenSource.Token
property.
CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
CancellationToken cancellationToken = cancellationTokenSource.Token;
You can then pass the cancellation token to any threads, tasks, or operations that should receive the cancellation notification.
How to cancel the asynchronous operation?
You can either use the Cancel()
or CancelAfter()
method from CancellationTokenSource
to cancel the token.
cancellationTokenSource.Cancel(); //Cancel immediately
cancellationTokenSource.CancelAfter(1000); //Cancel after given time
If you want to cancel the asynchronous APIs, the route endpoint should use the CancellationToken
delegate handler as mentioned below. Your code should check for a token.IsCancellationRequested
status periodically and acts based on the true/false
value.
app.MapGet("/ApiTest", async (CancellationToken token)
How do you know the operation is cancelled?
CancellationToken
has a property called IsCancellationRequested
returns true if the token has been cancelled.
You can also use the ThrowIfCancellationRequested
method to throw an OperationCanceledException if the token has been cancelled.
How to use cancellationtoken in C#?
The asynchronous operations must periodically check for cancellationToken.IsCancellationRequested
is true
. If true, you should write your logic to gracefully exit all the long-running processes.
while (!cancellationToken.IsCancellationRequested)
{
//Long running operations here.
}
Sometimes the OperationCanceledException
will be thrown, hence introduce the try-catch block to handle the exceptions.
try
{
//Operations that might throw OperationCanceledException on cancel
}
catch (OperationCanceledException)
{
//Handle the cancellation
}
Do the cleanup activities when cancellationToken.IsCancellationRequested
true or inside catch block of OperationCanceledException
. You may also use CancellationToken.Register()
to register your custom cleanup logic as below, which will be executed once the token is cancelled.
WebClient webClient= new WebClient();
cancellationToken.Register(() =>
{
webClient.CancelAsync();
});
Cancellationtoken example in c# (using WebAPI)
app.MapGet("/ApiTest", async (CancellationToken token) =>
{
var result = await DoWorkAsync(token);
return Results.Ok(result);
})
.WithName("ApiTest")
.WithOpenApi();
static async Task<string> DoWorkAsync(CancellationToken cancellationToken)
{
try
{
// A long-running operation like database, business logics
await Task.Delay(5000, cancellationToken);
return "Operation completed.";
}
catch (OperationCanceledException ex)
{
return "Operation canceled. (No output to client)";
}
}
If the above API is executed without cancellation, it will return the "Operation completed." message.
If the above API is cancelled, it will cancel the operation from
DoWorkAsync
method as well. Please note that no output will be returned to the client upon cancellation.
Cancellationtoken example using console app
using System;
using System.Threading;
class Program
{
static void Main(string[] args)
{
// Create a cancellation token source
CancellationTokenSource cts = new CancellationTokenSource();
// Pass the cancellation token to an asynchronous method
DoWorkAsync(cts.Token);
// Wait for user input to cancel the operation
Console.WriteLine("Press any key to cancel...");
Console.ReadKey();
// Cancel the operation by calling Cancel() on the cancellation token source
cts.Cancel();
Console.WriteLine("Operation canceled.");
Console.ReadKey();
}
static async void DoWorkAsync(CancellationToken cancellationToken)
{
try
{
// Simulate some long-running operation
await Task.Delay(5000, cancellationToken);
// Check if cancellation has been requested
if (cancellationToken.IsCancellationRequested)
{
Console.WriteLine("Operation canceled.");
}
else
{
Console.WriteLine("Operation completed.");
}
}
catch (OperationCanceledException)
{
Console.WriteLine("Operation canceled.");
}
}
}
Please note that the above code is auto-generated using AI.
General recommendations
Check the cancellation token periodically inside the long-running process. If cancelled, exit the process after handling necessary activities like closing database connections, releasing external resources, etc.
Wherever necessary, pass the cancellation token to all the asynchronous methods which can be cancelled at a later time.
Know when you’ve passed the point of no cancellation. Sometimes you may start changing the state of an object in the database and cancellation might lead to data inconsistency or other serious issues.
Don’t throw OperationCanceledException after you’ve completed the work, just because the token was signalled.
Summary
You should now understand how to use CancellationToken in C# to cancel the long-running operations when the request is cancelled. This will help us to save server resources and improve the application performance.
If you enjoyed this post and want to get more valuable tips and insights on .NET/C#, don’t forget to subscribe to my newsletter https://rajasekar.dev/newsletter and get notified whenever I publish a new article.
References
Recommended patterns for CancellationToken - Developer Support (microsoft.com)
How to Cancel a Task in C# using Cancellation Token - Dot Net Tutorials
Using a CancellationToken in .NET Core Web API | by Danielle | Medium
Why Do You Need a Cancellation Token in C# for Tasks? | HackerNoon
Top comments (0)