How to Use Cancellation Tokens in ASP.NET Core
By FoxLearn 2/3/2025 9:04:26 AM 154
In ASP.NET Core applications, it’s important to make long-running operations (like database queries, file processing, or background tasks) cancelable. This can be done either by setting a time limit or based on user input, ensuring the application remains responsive and can release resources.
Understanding Cancellation Tokens
A CancellationToken
is a lightweight object generated by a CancellationTokenSource
. When the CancellationTokenSource
is canceled, all associated CancellationToken
consumers are notified, and the IsCancellationRequested
property is set to true, signaling that the task should be canceled.
By passing a CancellationToken
to a long-running operation, like an HTTP request, you enable the task to be stopped if the user cancels the operation (for example, by refreshing the browser or closing the tab). This prevents unnecessary resource usage.
Using Cancellation Tokens with Async Tasks
Cancellation tokens are also useful for async tasks. In this case, a cancellation request tells the task to stop what it’s doing. The task checks the token periodically, and if cancellation is requested, it halts its operation.
Handling Long-Running Requests in ASP.NET Core
In ASP.NET Core applications, you may often encounter scenarios where long-running tasks are required, such as querying databases or handling large files. When initiating such tasks, it’s essential to pass cancellation tokens to these operations and propagate cancellation requests appropriately.
If a task exceeds a set timeout or the user cancels a request, the cancellation notification is passed to the cancellation token. It is crucial that all long-running tasks respect this cancellation and stop execution to free up resources.
Listening for Cancellation Requests
Cancellation requests can be monitored by checking the IsCancellationRequested
property of the CancellationToken
, as shown below:
while(!cancellationToken.IsCancellationRequested) { // Perform your task here }
Alternatively, you can use the ThrowIfCancellationRequested()
method to automatically throw an exception when cancellation is requested:
while(true) { // Perform task here cancellationToken.ThrowIfCancellationRequested(); }
Another method is to register a callback with the CancellationToken
:
WebClient webClient = new WebClient(); cancellationToken.Register(() => { webClient.CancelAsync(); });
Creating a Minimal API Handler with Cancellation
Let’s now walk through an example where we simulate a long-running request and incorporate cancellation. First, we’ll implement a basic handler without cancellation:
app.MapGet("/hello", async () => { app.Logger.LogInformation("Request started at: " + DateTime.Now.ToLongTimeString()); await Task.Delay(TimeSpan.FromSeconds(5)); app.Logger.LogInformation("Request completed at: " + DateTime.Now.ToLongTimeString()); return "Success"; });
When you hit the /hello
endpoint, the handler runs completely even if the user tries to cancel the request by refreshing the page. The long-running task continues to completion regardless of user actions.
Adding Cancellation Token to the Handler
To handle cancellation, we inject the CancellationToken
into the handler and pass it to the Task.Delay()
method:
app.MapGet("/hello", async (CancellationToken token) => { app.Logger.LogInformation("Request started at: " + DateTime.Now.ToLongTimeString()); await Task.Delay(TimeSpan.FromSeconds(5), token); app.Logger.LogInformation("Request completed at: " + DateTime.Now.ToLongTimeString()); return "Success"; });
Now, when you refresh the browser during the request, the operation will stop immediately. You’ll notice the logs show the request was canceled before completing, and a TaskCancelledException
is thrown.
Checking for Cancellation in ASP.NET Core
You can also check the cancellation state at any point by checking the IsCancellationRequested
property of the CancellationToken
. If the token has been canceled, it will return true
. You can then throw an exception or handle the cancellation as needed:
if (token.IsCancellationRequested) { app.Logger.LogInformation("Request has been canceled.."); throw new OperationCanceledException(); }
Best Practices for Using Cancellation Tokens
Cancellation tokens are essential for operations that involve significant resources, like database calls or long-running background tasks. However, they aren’t always appropriate for controller actions that modify application state, as canceling these types of requests may cause inconsistency. Instead, they are best used for operations where stopping the process mid-way won’t lead to negative side effects, such as in resource-intensive background tasks or network calls.
In this article, we used Task.Delay()
to simulate a long-running operation. However, you can substitute this with your own long-running processes, such as file handling, database queries, or HTTP requests.
Using cancellation tokens effectively ensures that your application remains responsive and efficient, especially when handling user-driven cancellations or timeouts.
- Options Pattern In ASP.NET Core
- Implementing Rate Limiting in .NET
- IExceptionFilter in .NET Core
- Repository Pattern in .NET Core
- CRUD with Dapper in ASP.NET Core
- How to Implement Mediator Pattern in .NET
- How to use AutoMapper in ASP.NET Core
- How to fix 'asp-controller and asp-action attributes not working in areas'