When we start to code using the CQRS pattern with mediatR library you can see that our handlers (queries and commands) always implement the handle method with a parameter called cancellationToken of type System.Threading.CancellationToken.
public async Task<List<SomeClass>> Handle(Query request, CancellationToken cancellationToken)
{
}
Actually, that parameter gives us the possibility to cancel the execution if something went wrong, for example:
-A user closes the window before the request finishes. -A user hit the cancel button. -Some error between the user interface and the backend.
In the example below, we throw a ThrowIfCancellationRequested exception
if a cancellation is requested by the user, then in the catch if the exception is a TaskCanceledException
we write in the console that the task was canceled.
public async Task<List<SomeClass>> Handle(Query request, CancellationToken cancellationToken)
{
try
{
for (int i = 0; i < 100; i++)
{
cancellationToken.ThrowIfCancellationRequested();
await Task.Delay(1000, cancellationToken);
}
}
catch (Exception ex) when (ex is TaskCanceledException)
{
_logger.LogInformation($"task was cancelled");
}
return await _context.Activities.ToListAsync();
}
Now we need to receive the cancellation token from our API
[HttpGet]
public async Task<ActionResult<List<SomeClass>>> GetList(CancellationToken token)
{
return await Mediator.Send(new List.Query(),token);
}
we add a parameter CancellationToken token
, as a parameter from our endpoint, and then pass it to mediatR as the second parameter.
now every time that the request is canceled from the client, a TaskCanceledException
will be throw from our query handler, allowing us to act and do something to rollback the execution in progress.