I see this code in front of me and I am suspicious:
CancellationTokenSource _cts;
public void Dispose();
{
_cts.Cancel();
_cts.Dispose();
_task.
Is it safe to call _cts.Dispose() straight after cancel?
In order to know that, we need to understand what happens when we cancel a CancellationTokenSource
.
When you cancel a CancellationTokenSource
, it goes on to invoke any callbacks registered via the CancellationToken
, which holds a reference to it's parent source via the CancellationToken.Register()
method.
When you dispose a CTS, any linking callback that was registered is attempted to be unregistered from the token. If it's currently executing, it will wait until it's delegate is complete.
Which means, that although you've disposed your CTS, it's object is still referenced by the token. Hence, it still isn't eligible for collection.
Now let's look at CancellationToken.IsCancellationRequested
:
public bool IsCancellationRequested
{
get
{
return m_source != null && m_source.IsCancellationRequested;
}
}
This means that while disposed, checking the cancellation will yield true. This means, that it is safe for you to wait on the tasks completion after calling dispose.
As a side note, if you (for some reason) try to pass a token via it's disposed CancellationTokenSource
, you will hit an ObjectDisposedException
.
Edit:
Two things I want to add. First, let me say that I don't recommend using this approach. It should work for some code execution paths, but not for all. CancellationTokenSource
should normally be disposed only if you use it's WaitHandle
property. Otherwise, it is fine to leave it up to the GC to do the cleaning. But, as this is a matter of flavor, you may choose whichever you like. I would certainly advise to dispose only after you're certain the task has observed the cancellation request.
As per usage of WaitHandle
, it will be disposed and nulled out once you dispose, so it will not be reachable.