ASP.NET Core  

Cancellation Tokens in ASP.NET Core: How to Cancel Long-Running Requests Correctly

Modern web applications frequently execute long-running operations such as database queries, file uploads, report generation, external API calls, and background processing. However, users may close their browser, mobile devices may lose connectivity, or reverse proxies may terminate requests before these operations complete.

Without proper cancellation support, the application continues processing requests that no longer have an active client, wasting CPU, memory, database connections, and network resources. ASP.NET Core provides built-in support for CancellationToken, enabling applications to stop unnecessary work as soon as a request is cancelled.

Rather than ignoring cancelled requests, this article explains how to use CancellationToken throughout an ASP.NET Core application to improve scalability, responsiveness, and resource utilization.

Note: Cancellation tokens are cooperative. They signal that work should stop, but your code must explicitly observe the token and terminate gracefully.

Why Cancellation Tokens Matter

Ignoring cancelled requests can lead to:

  • Wasted CPU cycles

  • Unnecessary database queries

  • Long-running background operations

  • Connection pool exhaustion

  • Increased memory usage

  • Poor application scalability

Supporting cancellation allows the application to free resources immediately when work is no longer needed.

Common Scenarios for Cancellation

Cancellation tokens are commonly used with:

  • Database queries

  • External HTTP requests

  • File uploads

  • File downloads

  • Report generation

  • Long-running calculations

  • Background services

  • Streaming responses

Almost every asynchronous operation in ASP.NET Core supports cancellation.

Request Cancellation Flow

flowchart LR

A[Client Request]
B[ASP.NET Core]
C[Controller]
D[Service]
E[(Database)]

A --> B
B --> C
C --> D
D --> E

A -. Client Disconnect .-> B
B --> F[CancellationToken Triggered]
F --> D
D --> C
C --> B

Once the client disconnects, ASP.NET Core signals the cancellation token, allowing ongoing operations to stop.

Receiving a CancellationToken

ASP.NET Core automatically injects a cancellation token into controller actions.

[HttpGet]
public async Task<IActionResult> GetProducts(
    CancellationToken cancellationToken)
{
    var products =
        await service.GetProductsAsync(
            cancellationToken);

    return Ok(products);
}

The token is automatically linked to the lifetime of the HTTP request.

Passing the Token Through Services

Pass the token through every application layer.

public async Task<List<Product>>
    GetProductsAsync(
        CancellationToken cancellationToken)
{
    return await repository
        .GetAllAsync(cancellationToken);
}

Avoid creating new cancellation tokens unless necessary.

Using Cancellation with EF Core

Entity Framework Core supports cancellation.

var products =
    await context.Products
        .ToListAsync(cancellationToken);

If the request is cancelled, EF Core stops executing the query whenever possible.

Using Cancellation with HttpClient

Forward the cancellation token to outbound HTTP calls.

var response =
    await httpClient.GetAsync(
        "/products",
        cancellationToken);

This prevents waiting for external services after the client has already disconnected.

Cancelling Long-Running Operations

Check the token periodically during lengthy processing.

for (int i = 0; i < 100; i++)
{
    cancellationToken.ThrowIfCancellationRequested();

    await ProcessItemAsync(i);
}

The operation exits immediately when cancellation is requested.

Background Service Cancellation

Hosted services automatically receive a cancellation token.

public class Worker : BackgroundService
{
    protected override async Task ExecuteAsync(
        CancellationToken stoppingToken)
    {
        while (!stoppingToken.IsCancellationRequested)
        {
            await ProcessQueueAsync();

            await Task.Delay(
                1000,
                stoppingToken);
        }
    }
}

The worker stops gracefully during application shutdown.

Cancellation Workflow

sequenceDiagram

participant Client
participant API
participant Database

Client->>API: Request
API->>Database: Query

Client-->>API: Disconnect

API->>Database: Cancel Query

Database-->>API: Operation Cancelled

API-->>Client: Connection Closed

Cancellation prevents unnecessary work after the client is no longer waiting for a response.

Operations That Support Cancellation

OperationSupports Cancellation
EF Core Queries
HttpClient
File Streams
Task.Delay
BackgroundService
ASP.NET Core MVC

Most modern .NET APIs include overloads that accept a CancellationToken.

Common Production Mistakes

ProblemRoot Cause
Database queries continue after disconnectCancellation token not passed to EF Core
External API calls continue runningToken not forwarded to HttpClient
High CPU usageLong loops ignore cancellation
Background services hang during shutdownIsCancellationRequested never checked
Resource exhaustionCancelled requests continue processing
Unexpected exceptionsOperationCanceledException not handled appropriately

Many scalability issues are caused by ignoring cancellation rather than expensive operations themselves.

Best Practices

  • Accept a CancellationToken in every asynchronous endpoint.

  • Pass the token through every application layer.

  • Use asynchronous APIs that support cancellation.

  • Check cancellation during long-running loops.

  • Handle OperationCanceledException appropriately.

  • Test cancellation behavior under production-like workloads.

  • Avoid creating unnecessary linked cancellation tokens.

Common Anti-Patterns

Avoid these common mistakes:

  • Ignoring the provided cancellation token.

  • Creating a new CancellationTokenSource for every request.

  • Catching and suppressing OperationCanceledException without understanding the cause.

  • Performing expensive cleanup after cancellation.

  • Blocking threads with synchronous code.

  • Assuming cancellation immediately terminates execution.

FAQ

Does ASP.NET Core automatically cancel requests?

Yes. When the client disconnects or the request is aborted, ASP.NET Core signals the associated CancellationToken. Your application must observe that token and stop processing.

Should every asynchronous method accept a CancellationToken?

In most cases, yes. Passing the token through the application allows cancellation to propagate naturally from the HTTP request to lower layers.

Is OperationCanceledException an error?

Not usually. It indicates that an operation ended because cancellation was requested. In many scenarios, it represents expected behavior rather than an application failure.

Does cancellation roll back database transactions?

Cancellation stops ongoing work when supported by the underlying provider, but transaction rollback depends on how the transaction is managed. Ensure transactions are handled correctly to maintain data consistency.

Conclusion

Cancellation tokens are a fundamental part of building scalable and efficient ASP.NET Core applications. By propagating cancellation through controllers, services, database operations, and external API calls, you can avoid wasting resources on work that no longer benefits the client.

Implementing cancellation consistently not only improves application performance but also enhances reliability during client disconnects, deployment events, and long-running operations, making your applications better prepared for production workloads.