Cancellation token and APIs
Why you should start using them in your backend services
Ever encountered a situation where you got frustrated with an unresponsive
website/app and you hit the refresh button
.
Of course you have. Its 2021 and everyone wants instant gratification.
On the Web, the end user always has the cancel/refresh button at their disposal, and they wont hesitate to use it. But what about the process that was initiated on the server side? How do we as backend devs
take care of that, we don't want to keep on processing a cancelled operation
and exhaust
our resources, do we?
In this post we will take a look at cancellation tokens in .NET and how we can leverage them for situations just like these.
Cancellation tokens
Cancellation tokens or the cancellation model in general belong to the Task Parallel Library
. The library provides us a Type called CancellationTokenSource
which encapsulates a CancellationToken
object within it. CancellationTokenSource also provides us with other extensions to manage a cancelled operation.
On a high level, to make use of the cancellation model we need to do the following
- Run our logic inside a Task, this would accept a cancellation token
- We keep on monitoring for cancellation requests by taking a look at the cancellation token and handle them gracefully
- From outside our logic, some other operation informs our task that a cancellation is requested
Now since we are dealing with APIs in this post, there is no need for us to manage CancellationTokenSource as it is inherently injected
by the framework as part of each request. All we have to do is manage the cancellation token.
Lets take a look at some snippets where we will pass CancellationToken as a parameter to our API endpoint. There is no need to build or manage the CancellationTokenSource.
ā”Make use of framework methods which accept cancellation tokens
[HttpPost("~/longoperation")]
public async Task<ActionResult> AnnoyingLongRunningOperation(CancellationToken token)
{
try
{
_logger.LogInformation("Calling long running operation");
await Task.Delay(1000000000, token); // our annoying long running task
_logger.LogInformation("Done with long running operation");
}
catch (OperationCanceledException ex)
{
// handle ex
_logger.LogError("Long running operation was cancelled");
}
return new OkObjectResult("Done!");
}
After I initiated the request using Postman
, I immediately hit cancel
and this is how the application behaves.
As you can see,
Task.Delay()
throws an OperationCanceledException
as soon as it encounters a cancellation request (it has its own logic to dispose objects etc), and we can handle that exception gracefully in our logic.
Likewise, we can leverage alot of framework methods which already accept cancellation tokens.
ā”Write your own method which accepts a cancellation token
[HttpPost("~/longoperation")]
public async Task<ActionResult> AnnoyingLongRunningOperation(CancellationToken token)
{
try
{
_logger.LogInformation("Calling long running operation");
await ActualAnnoyingLongRunningOperationAsync(token);
_logger.LogInformation("Done with long running operation");
}
catch (OperationCanceledException ex)
{
// handle ex
_logger.LogError("Long running operation was cancelled");
}
return new OkObjectResult("Done!");
}
private async Task ActualAnnoyingLongRunningOperationAsync(CancellationToken token)
{
for(int i=0;i<100;i+=2)
{
_logger.LogInformation($"Loop counter : {i}");
await Task.Delay(100); // 100 important operations
}
token.ThrowIfCancellationRequested();
// 100 other important operations
}
Again, after I initiated the request using Postman
, I immediately hit cancel
and this is how the application behaves now.
This time you can see that we have managed cancellation on our own terms, we have made sure the loop runs completely(could represent some necessary backend job etc) before cancellation is processed.
In both the cases, the task that was consuming needless server resources, was disposed
from the pool.
Cancellation model is an easy and neat feature we should always look out for implementing in our projects and I hope this post gave you some insights.
Thank you for reading. Cheers!
Take a look at my other post Cancellation token multifold š which talks about different mix and matches of cancellation token usage.