Is code that disposes CancellationTokenSource while tasks are canceling correct?

旧街凉风 提交于 2019-12-18 14:51:45

问题


I see this code in front of me and I am suspicious:

CancellationTokenSource _cts;

public void Dispose();
{
    _cts.Cancel();
    _cts.Dispose();
    _task.Wait(); //wait for the task to be canceled!?
}

Is it safe to call _cts.Dispose() straight after cancel? Wouldn't that dispose of underlying resources of the CancellationTokenSource that are needed for the task being cancelled to successfully Wait on the CancellationToken, if it wanted to do so?


回答1:


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.

Now, when you dispose a CTS, any linking callback that was registered is attempted to be de-registered 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.



来源:https://stackoverflow.com/questions/29779842/is-code-that-disposes-cancellationtokensource-while-tasks-are-canceling-correct

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!