Can I pass CancellationToken as parameter in AspNetCore WebAPI

2.6k Views Asked by At

As far as I know if I use services.AddControllers() or services.AddMvc()extension in my Startup.cs "MVC will automatically bind any CancellationToken parameters in an action method.

I have the following TestController and TestService as Transient service.

According to this informations, when the auto-binded CancellationToken IsCancellationRequested will the tokens that I have passed as parameters be also canceled?

public class TestController : ControllerBase
{
    private readonly ITestService _testService;

    public TestController(ITestService testService)
    {
        _testService = testService;
    }

    [HttpGet, ActionName("Get")]
    public async Task<IActionResult> GetAsync(CancellationToken cancellationToken)
    {
        await _testService.GetAsync(cancellationToken);
        return Ok();
    }
}

public class TestService : ITestService
{
    public async Task GetAsync(CancellationToken cancellationToken)
    {
        //I also send the cancellationToken as a parameter to external API calls
    }
 }
1

There are 1 best solutions below

1
On

when the auto-binded CancellationToken IsCancellationRequested will the tokens that I have passed as parameters be also canceled?

By injecting a CancellationToken into your action method, which will be automatically bound to the HttpContext.RequestAborted token for the request. After the request is cancelled by the user refreshing the browser or click the "stop" button, the original request is aborted with a TaskCancelledException which propagates back through the MVC filter pipeline, and back up the middleware pipeline. Then, You could check the value of IsCancellationRequested and exit the action gracefully. In this scenario, there is no need to transfer the CancellationToken as parameters.

If you want to Cancel an Async task, since, CancellationTokens are lightweight objects that are created by a CancellationTokenSource. When a CancellationTokenSource is cancelled, it notifies all the consumers of the CancellationToken. So, you could call the Cancel() method to cancel the task.

Check the following sample:

        var cts = new CancellationTokenSource();
        //cts.CancelAfter(5000);//Request Cancel after 5 seconds

        _logger.LogInformation("New Test start");
        var newTask = Task.Factory.StartNew(state =>
        {
            int i = 1;
            var token = (System.Threading.CancellationToken)state;
            while (true)
            {
                Console.WriteLine(i);
                i++;
                if (i == 10)
                {
                    cts.Cancel(); //call the Cancel method to cancel.
                }
                _logger.LogInformation("thread running " + DateTime.Now.ToString());
                Thread.Sleep(1000);
                token.ThrowIfCancellationRequested();
            }
        }, cts.Token, cts.Token);

        try
        {
            newTask.Wait(10000);
        }
        catch
        {
            Console.WriteLine("Catch:" + newTask.Status);
        }

        _logger.LogInformation("Test end");

More detail information about using CancellationToken, please check the following articles:

Using CancellationTokens in ASP.NET Core MVC controllers