When To Use CancellationToken?:
In a web application request abortion or orphan, requests are quite common. On users disconnected by network interruption or navigating between multiple pages before proper response or closing of the browser, tabs make the request aborted or orphan. An orphan request can't deliver a response to the client, but it will execute all steps(like database calls, HTTP calls, etc) at the server. Complete execution of an orphan request at the server might not be a problem generally if at all requests need to work on time taking a job at the server in those cases might be nice to terminate the execution immediately. So CancellationToken can be used to terminate a request execution at the server immediately once the request is aborted or orphan.
Here we are going to see some sample code snippets about implementing a CancellationToken for Entity FrameworkCore, Dapper ORM, and HttpClient calls in Asp.NetCore MVC application.
Note: The sample codes I will show in this demo are not production codes, here I'm making my database or HTTP calls as long time taking tasks explicitly to demonstrate the execution of CancellationToken.
CancellationToken For Entity Framework Core Calls:
Let's have look at a piece of code that takes a long time for Entity Framework Core for fetching the data from the database.
MVC Action Method Using EfCore:
[HttpGet] public async Task<IActionResult> GetGadgetsEfCall() { Console.WriteLine("Before Ef call"); List<Gadgets> result = new List<Gadgets>(); for (int i = 0; i < 10000; i++) { result = await _dbContext.Gadgets.ToListAsync(); } Console.WriteLine("After Ef call"); return View("GadgetsEfCall", result); }
- (Line: 6-9) Here is the piece of code that executes for a long time that involves efcore calls.
Now we can terminate the execution of an orphan request by using the CancellationToken. So let's update our code as below:
MVC Action Method Using EfCore With CancellationToken:
MVC Action Method Using EfCore With CancellationToken:
[HttpGet] public async Task<IActionResult> GetGadgetsEfCall(CancellationToken cancellationToken) { Console.WriteLine("Before Ef call"); List<Gadgets> result = new List<Gadgets>(); for (int i = 0; i < 10000; i++) { result = await _dbContext.Gadgets.ToListAsync(cancellationToken); } Console.WriteLine("After Ef call"); return View("GadgetsEfCall", result); }
- (Line: 2) Injected the 'CancellationToken'.
- (Line: 8) Passing our token to 'ToListAsync' of the Entity Framework Core.
Cancellation Token For Dapper Micro-ORM Calls:
Let's have look at a piece of code that takes a long time for Dapper Micro-ORM for fetching the data from the database.
MVC Action Method Using Dapper:
public async Task<IActionResult> GetGadgetsDapperCall() { Console.WriteLine("Before Dapper ORM call"); List<Gadgets> results = new List<Gadgets>(); using (var conn = Connection) { string delayMinutes = "00:00:10"; var query = @"WAITFOR DELAY @delayMinutes SELECT * FROM Gadgets"; results = (await conn.QueryAsync<Gadgets>(query, new { delayMinutes })).ToList(); cancellationToken:token))).ToList(); } Console.WriteLine("After Dapper ORM call"); return View("GadgetsDapperCall", results); }
- (Line: 7-9) Here I created a raw SQL query that needs to initially be delayed by 10seconds to make it a long time running task.
Now we can terminate the execution of an orphan request by using the CancellationToken. So let's update our code as below:
MVC Action Method Using Dapper With CancellationToken:
public async Task<IActionResult> GetGadgetsDapperCall(CancellationToken token) { Console.WriteLine("Before Dapper ORM call"); List<Gadgets> results = new List<Gadgets>(); using (var conn = Connection) { string delayMinutes = "00:00:10"; var query = @"WAITFOR DELAY @delayMinutes SELECT * FROM Gadgets"; results = (await conn.QueryAsync<Gadgets>(new CommandDefinition(query, new { delayMinutes }, cancellationToken:token))).ToList(); } Console.WriteLine("After Dapper ORM call"); return View("GadgetsDapperCall", results); }
- (Line: 1) Injected 'CancellationToken' into the action method.
- (Line: 10) Passed the token to the Dapper query execution.
CancellationToken For HttpClient Calls:
Let's have look at a piece of code that takes a long time for fetching data from external API using the HttpClient instance.
MVC Action Method Using HttpClient:
public async Task<IActionResult> GetPostAPI() { Console.WriteLine("Before External API call"); var results = new List<Post>(); for (int i = 0; i < 10; i++) { results = await _httpClient.GetFromJsonAsync<List<Post>>("/typicode/demo/posts" ); } Console.WriteLine("After External API call"); return View("PostAPI", results); }
- (Line: 5-8) Consider these lines of code as time taking logic of my HttpClient call.
Now we can terminate the execution of an orphan request by using the CancellationToken. So let's update our code as below:
MVC Action Method Using HttpClient With CancellationToken:
public async Task<IActionResult> GetPostAPI(CancellationToken token) { Console.WriteLine("Before External API call"); var results = new List<Post>(); for (int i = 0; i < 10; i++) { results = await _httpClient.GetFromJsonAsync<List<Post>>("/typicode/demo/posts" , token); } Console.WriteLine("After External API call"); return View("PostAPI", results); }
- (Line: 1) Injected 'CancellationToken' into the action method.
- (Line: 7) Passing the token to the HttpClient call.
Support Me!
Buy Me A Coffee
PayPal Me
Video Session:
Wrapping Up:
Hopefully, I think this article delivered some useful information Usage of CancellationToken in asp.net core applications. I love to have your feedback, suggestions, and better techniques in the comment section below.
Your way of explaining the things is very extraordinary, Is there any article for uploading large files (zip files) on azure blob storage and I want to cancel it if required and progress bar should be shown
ReplyDeleteI had problem with AuthenticationState not being validated each time login or logout action was called. I've been searching for the solution of this problem for some time and I found it here. Many thanks you wrote this article.
ReplyDelete