Coder Perfect

When should you get rid of CancellationTokenSource?


CancellationTokenSource is a one-time use class. A short look in Reflector reveals that KernelEvent is being used, which is a (very likely) unmanaged resource. The GC will not dispose of CancellationTokenSource because it lacks a finalizer.

Only one code snippet in the MSDN article Cancellation in Managed Threads, on the other hand, disposes of the token.

What’s the best approach to get rid of it in code?

Because it doesn’t have a Reset function to clean away the IsCancelRequested and Token fields, I assume it’s not reusable, therefore you should construct a new one every time you start a task (or a PLINQ query). Is this correct? If that’s the case, my concern is: what’s the best way to deal with Dispose on that many CancellationTokenSource instances?

Asked by George Mamaladze

Solution #1

Concerning whether or not calling Dispose on CancellationTokenSource is truly necessary… My project suffered a memory leak, and it turns out that CancellationTokenSource was the culprit.

My project has a service that is continually reading databases and firing off different tasks, and I was giving connected cancellation tokens to my workers, therefore cancellation tokens were not disposed of even after they had done processing data, resulting in a memory leak.

It’s stated explicitly in MSDN Cancellation in Managed Threads:

In my implementation, I utilized ContinueWith.

Answered by Gruzilkin

Solution #2

None of the present responses were satisfactory in my opinion. After doing some study, I came across this response from Stephen Toub (reference):

The bold part, in my opinion, is the most crucial. He uses the phrase “more impactful,” which is a little ambiguous. I’m taking it to suggest that in those cases, calling Dispose should be done; otherwise, Dispose isn’t required.

Answered by Jesse Good

Solution #3

CancellationTokenSource should never be used again.

The best way to dispose of trash is determined by the situation. You provide a number of alternative scenarios.

There is always a solution. IDisposable instances should be disposed of at all times. Because they’re either fast samples to explain essential functionality or because including all attributes of the class being presented would be too complex for a sample, samples rarely do. The sample is just that: a sample. It is not always (or even usually) production-quality code. Not all examples are suitable for direct incorporation into production code.

Answered by Samuel Neff

Solution #4

I looked for the CancellationTokenSource in ILSpy, but all I could find was m KernelEvent, which is actually a ManualResetEvent, which is a wrapper class for a WaitHandle object. The GC should handle this correctly.

Answered by Bryan Crosby

Solution #5

This answer continues to show up in Google searches, and I believe the most popular answer does not provide the whole story. After reviewing the source code for CancellationTokenSource (CTS) and CancellationToken (CT), I believe the following code sequence is sufficient for most use cases:

if (cancelTokenSource != null)
    cancelTokenSource = null;

The synchronization object underpinning the WaitHandle property in both the CTS and CT classes is the m kernelHandle internal field discussed before. If you access that property, it is merely instantiated. So, unless you’re utilizing WaitHandle in your Task for some old-school thread synchronization, executing dispose has no effect.

Of course, if you’re using it, you should follow the advice of the other replies and wait until any WaitHandle activities that require the handle are finished before calling Dispose, because the outcomes are undefined, as mentioned in the Windows API documentation for WaitHandle.

Answered by jlyonsmith

Post is based on