Correct pattern to dispose of cancellation token source

To ensure that a CTS (CancellationTokenSource) associated with a fire-and-forget Task will be eventually disposed, you should attach a continuation to the task, and dispose the CTS from inside the continuation. This creates a problem though, because another thread could call the Cancel method while the object is in the midst of its disposal, and according to the documentation the Dispose method is not thread-safe:

All public and protected members of CancellationTokenSource are thread-safe and may be used concurrently from multiple threads, with the exception of Dispose(), which must only be used when all other operations on the CancellationTokenSource object have completed.

So calling Cancel and Dispose from two different threads concurrently without synchronization is not an option. This leaves only one option available: to add a layer of synchronization around all public members of the CTS class. This is not a happy option though, for several reasons:

  1. You must write the thread-safe wrapper class (write code)
  2. You must use it every time you start a cancelable fire-and-forget task (write more code)
  3. Incur the performance penalty of the synchronization
  4. Incur the performance penalty of the attached continuations
  5. Having to maintain a system that has become more complex and more bug-prone
  6. Having to cope with the philosophical question why the class was not designed to be thread-safe in the first place

So my recommendation is to do the alternative, which is simply to leave the CTS undisposed, only in these cases where you can't await the completion of its associated tasks. In other words if it's not possible to enclose the code that uses the CTS in a using statement, just let the garbage collector to do the reclaiming of the reserved resources. This means that you'll have to disobey this part of the documentation:

Always call Dispose before you release your last reference to the CancellationTokenSource. Otherwise, the resources it is using will not be freed until the garbage collector calls the CancellationTokenSource object's Finalize method.

...and this:

The CancellationTokenSource class implements the IDisposable interface. You should be sure to call the CancellationTokenSource.Dispose method when you have finished using the cancellation token source to free any unmanaged resources it holds.

If this makes you feel a bit dirty, you are not alone. You may feel better if you think that the Task class implements the IDisposable interface too, but disposing task instances is not required.


The correct practice is second - you dispose of the CancellationTokenSource after you are sure the task is cancelled. CancellationToken relies on information from CancellationTokenSource to function properly. While the current implementation CancellationToken is written in such a way that is will still work even without throwing exceptions if the CTS it was created from is disposed, it may not behave properly or always as expected.