Search code examples
c#asp.net-web-apidisposecancellation-token

Calling cancellationToken.Cancel() in Dispose of Controller?


I have controller, where I create a Cancellation Token in the constructor and use it in a long running await task (). Does disposing the Cancellation token in Controller.Dispose() causes the long running task to cancel?

public class SomeController : BaseInternalController
{
    private CancellationTokenSource cancellationTokenSource;

    public MyController()
    {
        cancellationTokenSource = new CancellationTokenSource();
    }

    public async Task<HttpResponseMessage> Post(SomeData data)
    {
        foreach (var item in data)
        {
            await longRunningTask(item, cancellationTokenSource.token);
        }

    }

    protected override void Dispose(bool disposing)
    {
        if (cancellationTokenSource != null)
        {
            cancellationTokenSource.Cancel();
            cancellationTokenSource.Dispose();
            cancellationTokenSource = null;
        }
        base.Dispose(disposing);
    }
}

Solution

  • Does disposing the Cancellation token in Controller.Dispose() causes the long running task to cancel?

    Depends on how your longRunningTask was implemented. In this method you should explicitly check whether the cancellation is requested:

    token.ThrowIfCancellationRequested();
    

    After invoking of this method your task will be cancelled.

    Cancellation example

    If in the following example the ThrowIfCancellationRequested would not be invoked, the task would be run forever:

    var cts = new CancellationTokenSource();
    Task.Run(() =>
    {
        while (true)
            cts.Token.ThrowIfCancellationRequested();
    }, cts.Token);
    

    You can learn more about cancellation here.


    Note that after setting the cancellationTokenSource to null, you can get NullReferenceException in your foreach loop. I would suggest to copy your token into a local variable:

    public async Task<HttpResponseMessage> Post(SomeData data)
    {
        var token = cancellationTokenSource.Token;
        foreach (var item in data)
        {
            await longRunningTask(item, token);
        }
    }