Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When to dispose CancellationTokenSource?

People also ask

Do CancellationTokenSource need to be disposed?

Since CancellationTokenSource has no finalizer, if we do not dispose it, the GC won't do it. On the other hand, if you look at the samples listed on the MSDN article Cancellation in Managed Threads, only one code snippet disposes of the token.

Can a CancellationTokenSource be reused?

CancellationTokenSource is quite a heavyweight object and its not normally cancelled; however it can't be pooled or reused because its registrations cannot be cleared.

What is CancellationTokenSource in C#?

A CancellationTokenSource object, which provides a cancellation token through its Token property and sends a cancellation message by calling its Cancel or CancelAfter method. A CancellationToken object, which indicates whether cancellation is requested.

What is the purpose of CancellationToken?

A CancellationToken enables cooperative cancellation between threads, thread pool work items, or Task objects. You create a cancellation token by instantiating a CancellationTokenSource object, which manages cancellation tokens retrieved from its CancellationTokenSource. Token property.


Speaking about whether it's really necessary to call Dispose on CancellationTokenSource... I had a memory leak in my project and it turned out that CancellationTokenSource was the problem.

My project has a service, that is constantly reading database and fires off different tasks, and I was passing linked cancellation tokens to my workers, so even after they had finished processing data, cancellation tokens weren't disposed, which caused a memory leak.

MSDN Cancellation in Managed Threads states it clearly:

Notice that you must call Dispose on the linked token source when you are done with it. For a more complete example, see How to: Listen for Multiple Cancellation Requests.

I used ContinueWith in my implementation.


I didn't think any of the current answers were satisfactory. After researching I found this reply from Stephen Toub (reference):

It depends. In .NET 4, CTS.Dispose served two primary purposes. If the CancellationToken's WaitHandle had been accessed (thus lazily allocating it), Dispose will dispose of that handle. Additionally, if the CTS was created via the CreateLinkedTokenSource method, Dispose will unlink the CTS from the tokens it was linked to. In .NET 4.5, Dispose has an additional purpose, which is if the CTS uses a Timer under the covers (e.g. CancelAfter was called), the Timer will be Disposed.

It's very rare for CancellationToken.WaitHandle to be used, so cleaning up after it typically isn't a great reason to use Dispose. If, however, you're creating your CTS with CreateLinkedTokenSource, or if you're using the CTS' timer functionality, it can be more impactful to use Dispose.

The bold part I think is the important part. He uses "more impactful" which leaves it a bit vague. I'm interpreting it as meaning calling Dispose in those situations should be done, otherwise using Dispose is not needed.


You should always dispose CancellationTokenSource.

How to dispose it depends exactly on the scenario. You propose several different scenarios.

  1. using only works when you're using CancellationTokenSource on some parallel work that you're waiting. If that's your senario, then great, it's the easiest method.

  2. When using tasks, use a ContinueWith task as you indicated to dispose of CancellationTokenSource.

  3. For plinq you can use using since you're running it in parallel but waiting on all of the parallel running workers to finish.

  4. For UI, you can create a new CancellationTokenSource for each cancellable operation that is not tied to a single cancel trigger. Maintain a List<IDisposable> and add each source to the list, disposing all of them when your component is disposed.

  5. For threads, create a new thread that joins all the worker threads and closes the single source when all of the worker threads finished. See CancellationTokenSource, When to dispose?

There's always a way. IDisposable instances should always be disposed. Samples often don't because they're either quick samples to show core usage or because adding in all aspects of the class being demonstrated would be overly complex for a sample. The sample is just that a sample, not necessarily (or even usually) production quality code. Not all samples are acceptable to be copied into production code as is.


I took a look in ILSpy for the CancellationTokenSource but I can only find m_KernelEvent which is actually a ManualResetEvent, which is a wrapper class for a WaitHandle object. This should be handled properly by the GC.


This answer is still coming up in Google searches, and I believe the voted up answer does not give the full story. After looking over the source code for CancellationTokenSource (CTS) and CancellationToken (CT) I believe that for most use cases the following code sequence is fine:

if (cancelTokenSource != null)
{
    cancelTokenSource.Cancel();
    cancelTokenSource.Dispose();
    cancelTokenSource = null;
}

The m_kernelHandle internal field mentioned above is the synchronization object backing the WaitHandle property in both the CTS and CT classes. It is only instantiated if you access that property. So, unless you are using WaitHandle for some old-school thread synchronization in your Task calling dispose will have no effect.

Of course, if you are using it you should do what is suggested by the other answers above and delay calling Dispose until any WaitHandle operations using the handle are complete, because, as is described in the Windows API documentation for WaitHandle, the results are undefined.