Introduction
In C# asynchronous programming, cancellation tokens are a core feature used to manage the lifetime of asynchronous operations. They provide a cooperative cancellation mechanism, allowing tasks to be cancelled in a controlled manner.
This article explores advanced scenarios and best practices for using cancellation tokens in asynchronous C# programming.
Understanding CancellationTokens
A CancellationToken
is a struct that can be passed to asynchronous methods to request cancellation of an ongoing task.
It’s typically paired with a CancellationTokenSource
, which is used to signal that cancellation should occur.
Basic Usage
Here’s a basic example of using a cancellation token:
CancellationTokenSource cts = new CancellationTokenSource();
CancellationToken token = cts.Token;
async Task DoSomethingAsync(CancellationToken cancellationToken)
{
// Check for cancellation
cancellationToken.ThrowIfCancellationRequested();
// Perform async operation
}
// Usage
await DoSomethingAsync(token);
Advanced Scenarios
Linked Cancellation Tokens:
Combine multiple CancellationTokenSource
objects for scenarios where a task should respond to multiple cancellation requests.
CancellationTokenSource cts1 = new CancellationTokenSource();
CancellationTokenSource cts2 = new CancellationTokenSource();
CancellationTokenSource linkedCts = CancellationTokenSource.CreateLinkedTokenSource(cts1.Token, cts2.Token);
await DoSomethingAsync(linkedCts.Token);
Handling Timeout:
Implement a timeout by cancelling a task after a specified period.
CancellationTokenSource cts = new CancellationTokenSource(); cts.CancelAfter(TimeSpan.FromSeconds(30));
try
{
await DoSomethingAsync(cts.Token);
}
catch (OperationCanceledException)
{
// Handle cancellation or timeout
}
Graceful Task Cancellation:
Tasks should regularly check the cancellation token and clean up resources if cancellation is requested.
async Task DoWorkAsync(CancellationToken cancellationToken)
{
while(!cancellationToken.IsCancellationRequested)
{
// Do work here
}
// Clean up
}
Cancellation Callbacks:
Register callbacks on the CancellationToken
that will be called when cancellation is requested.
CancellationTokenSource cts = new CancellationTokenSource();
cts.Token.Register(() =>
{
// Code to execute on cancellation
});
Passing CancellationTokens in UI Applications:
In UI applications, use cancellation tokens to cancel background operations when the user closes a form or navigates away from a page.
Cancellation in Parallel Loops
Use cancellation tokens in parallel operations like Parallel.ForEach
or PLINQ queries.
ParallelOptions parallelOptions = new ParallelOptions
{
CancellationToken = cts.Token
};
Parallel.ForEach(source, parallelOptions, item =>
{
// Process item
});
Best Practices
- Check for Cancellation Frequently: Tasks should regularly check for cancellation to ensure prompt response to cancellation requests.
- Graceful Shutdown: Ensure that tasks clean up resources and exit gracefully when cancellation is requested.
- Avoid Using CancellationTokens for Non-Cancellable Operations: Only use cancellation tokens with operations that support cancellation.
- Thread Safety: Be aware that cancellation token callbacks are not guaranteed to execute on any particular thread.
Conclusion
Cancellation tokens in C# are a powerful mechanism for managing the lifetime and behavior of asynchronous operations.
By understanding their advanced uses and adhering to best practices, developers can write more responsive, efficient, and robust asynchronous code.
Proper use of cancellation tokens is essential for creating high-quality, user-friendly applications that handle long-running operations gracefully.