Search code examples
c#memorycancellationtokensource

is it necessary to cancel cancellationtoken before disposal


I'm using CancellationTokenSource for timeout purposes most of the time. To avoid forgetting dispose, when I'm done with the CancellationTokenSource, I'm using a using statement. But before the end of the using statement, I'm always doing a CancellationTokenSource.Cancel().

Is it necessary to cancel CancellationTokenSource before disposal if the cancellation hasn't been used?

Here is an example of code where I'm doing this.

using (CancellationTokenSource TokenSource = new CancellationTokenSource(nTimeout * 1000))
{
  for (int i = 0; i < nLoop; i++)
  {
    if (TokenSource.Token.IsCancellationRequested)
    {
      bSuccess = false;
      break;
    }

    await Task.Delay(cDelay);
    // do some work
  }

  TokenSource.Cancel();
}

Solution

  • After a CancellationTokenSource has been disposed tokens based on this source may throw ObjectDisposedException so you should not use CancellationTokenSource.Token after the source has been disposed. Fortunately, I don't see this happening in your code.

    When you cancel a CancellationTokenSource it changes state and notifies callbacks that have been registered for the token. However, when your code is about to dispose the CancellationTokenSource you are already done using the token and there is no need to cancel it.

    So in your case it is not necessary to cancel the CancellationTokenSource before disposing it. However, your use case is somewhat special. When you have a background task you should wait for the task to complete before disposing the source (as stated in my initial paragraph):

    using (var cts = new CancellationTokenSource()) {
        var task = Task.Run(() => DoSomething(cts.Token));
        // Cancel cts or let it cancel itself based on a timeout.
        // Then wait for the task to end.
        await task;
    }