Cancellation is an essential part of building responsive and scalable .NET applications. The CancellationToken type allows operations to be cancelled gracefully, helping applications free resources, stop unnecessary work, and respond quickly to user actions.
One of the most commonly used members of CancellationToken is IsCancellationRequested. However, many developers are unsure when they should check this property directly and when it is unnecessary.
This article explores the purpose of IsCancellationRequested, common usage patterns, and best practices.
Understanding IsCancellationRequested
IsCancellationRequested is a boolean property used with a CancellationToken in .NET that indicates whether cancellation has been requested for a particular operation.
Imagine you have a long-running task (downloading data, processing files, running a loop, etc.). You may want a way to tell that task:
"Stop what you're doing as soon as it's safe."A CancellationToken provides that signal.
Basic example
if (cancellationToken.IsCancellationRequested)
{
// Stop processing
}
When a caller invokes
CancellationTokenSource.Cancel(), the property becomes true.
using System;
using System.Threading;
var cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
// Request cancellation
cts.Cancel();
Console.WriteLine(token.IsCancellationRequested);
How IsCancellationRequested works with async/await
IsCancellationRequested is often used together with async/await, but it is not directly tied to await. Instead, it provides a way for asynchronous operations to know when they should stop.
When an async method is running, it can periodically check the token and decide whether to stop.
ProcessAsync(CancellationToken token)
{
for (int i = 0; i < 100; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("Cancellation requested.");
return;
}
await Task.Delay(100);
}
}
Here:
- The method is asynchronous because of
await. IsCancellationRequestedlets the method know cancellation was requested.- When cancellation is requested:
token.IsCancellationRequestedbecomestrue.- The loop exits.
- The method exits early when cancellation is detected.
What happens after an await?
Cancellation can be requested while the method is suspended at an await.
async Task ExampleAsync(CancellationToken token)
{
await Task.Delay(5000);
if (token.IsCancellationRequested)
{
return;
}
Console.WriteLine("Continuing work...");
}
Here:
- Method starts.
- Reaches
await Task.Delay(5000). - Control returns to caller.
cts.Cancel()is called.- Delay completes.
- Method resumes after await.
IsCancellationRequestedis now true.- Method exits.
So the relationship is that async/await enables asynchronous execution, while IsCancellationRequested is one way for that asynchronous code to cooperate with cancellation requests. They are commonly used together, but neither depends on the other.
When to Use IsCancellationRequested
Inside Long-Running Loops
One of the most common scenarios is a loop that performs continuous work. Without this check, the loop may continue running even after the caller requests cancellation.
while (!cancellationToken.IsCancellationRequested)
{
ProcessNextItem();
}
Examples include:
- Background workers
- Message processing systems
- File processing loops
- Data synchronization services
During CPU-Bound Operations
Many .NET APIs automatically support cancellation for asynchronous I/O operations. However, CPU-bound work often requires explicit checks.
foreach (var item in largeCollection)
{
if (cancellationToken.IsCancellationRequested)
{
break;
}
PerformComplexCalculation(item);
}
This allows expensive computations to stop promptly rather than wasting CPU resources.
Before Starting Expensive WorkSometimes cancellation may already have been requested before a costly operation begins. Checking early can prevent unnecessary processing.
if (cancellationToken.IsCancellationRequested)
{
return;
}
GenerateLargeReport();
Between Processing Stages
For multi-step workflows, checking cancellation between stages helps avoid starting work that is no longer needed.
await DownloadDataAsync(cancellationToken);
if (cancellationToken.IsCancellationRequested)
{
return;
}
await ProcessDataAsync(cancellationToken);
if (cancellationToken.IsCancellationRequested)
{
return;
}
await SaveResultsAsync(cancellationToken);
This pattern is useful in ETL pipelines, data imports, and batch processing systems.
When Not to Use IsCancellationRequested
When Method Already Support Cancellation
List<students>= await dbcontext.Students.ToListAsync(token);
When APIs Already Support Cancellation
await httpClient.GetAsync(url, cancellationToken);
Avoid Excessive Polling
if (cancellationToken.IsCancellationRequested) { }
if (cancellationToken.IsCancellationRequested) { }
if (cancellationToken.IsCancellationRequested) { }
Best Practices
- Pass
CancellationTokenthrough allasynclayers. - Check cancellation in long-running loops.
- Check before expensive CPU-bound work.
- Prefer
ThrowIfCancellationRequested()for standard cancellation behavior. - Avoid unnecessary polling.
- Let framework APIs handle cancellation whenever possible.
Summary
CancellationToken.IsCancellationRequested is most useful when your code performs long-running or CPU-intensive work that cannot automatically respond to cancellation requests. It allows your application to stop gracefully, conserve resources, and improve responsiveness.
For most application code, use cancellation-aware APIs and prefer ThrowIfCancellationRequested() when cancellation should immediately end execution. Reserve direct checks of IsCancellationRequested for situations where you need custom cancellation logic or controlled shutdown behavior.
Thanks