Advanced Use of Async Cancellation Tokens in C#

Advanced Use of Async Cancellation Tokens in C#

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 ctsnew 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 cts1new CancellationTokenSource(); 
CancellationTokenSource cts2new 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 ctsnew 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 ctsnew 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 parallelOptionsnew 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.

Stephen

Hi, my name is Stephen Finchett. I have been a software engineer for over 30 years and worked on complex, business critical, multi-user systems for all of my career. For the last 15 years, I have been concentrating on web based solutions using the Microsoft Stack including ASP.Net, C#, TypeScript, SQL Server and running everything at scale within Kubernetes.