取消任务时处理CancellationTokenSource的代码是否正确? [英] Is code that disposes CancellationTokenSource while tasks are canceling correct?

查看:232
本文介绍了取消任务时处理CancellationTokenSource的代码是否正确?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我眼前看到此代码,并且对此表示怀疑:

  CancellationTokenSource _cts; 

public void Dispose();
{
_cts.Cancel();
_cts.Dispose();
_task.Wait(); //等待任务取消!
}

取消后直接调用_cts.Dispose()是否安全?

解决方案:不是要取消任务以成功完成CancellationToken时需要的CancellationTokenSource的基础资源吗?

方案


取消后立即调用_cts.Dispose()是否安全?


为了知道这一点,我们需要了解当取消 CancellationTokenSource 时会发生什么。



当您取消 CancellationTokenSource 后,它将继续调用通过 CancellationToken 注册的任何回调,该回调保留对其父源的引用通过 CancellationToken.Register()方法。



处置CTS时,所有已注册的链接回调都会被释放。试图从令牌中注销。如果它当前正在执行,它将等待直到委托完成。



这意味着,尽管您已经处置了CTS,但该对象仍被令牌引用。因此,它仍然不符合收集条件。



现在让我们看一下 CancellationToken.IsCancellationRequested

 公共布尔IsCancellationRequested 
{
get
{
return m_source!= null& m_source.IsCancellationRequested;
}
}

这意味着在处置时,检查取消将产生真正。这意味着,您可以安全地在调用dispose之后等待任务完成。



请注意,如果您(出于某种原因)尝试通过通过丢弃 CancellationTokenSource 令牌,您将遇到 ObjectDisposedException



编辑:



我想添加两件事。首先,我不建议您使用这种方法。它应适用于某些代码执行路径,但不适用于所有代码。通常,只有在使用 CancellationTokenSource 属性的 WaitHandle 属性时,才应将其丢弃。否则,最好将其留给GC进行清洁。但是,由于这是一个风味问题,您可以选择任意一个。我当然会建议仅在您确定任务观察到取消请求后才进行处置。



根据 WaitHandle ,则将其丢弃并在您处置后将其清空,因此它无法访问。


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?

解决方案

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.

这篇关于取消任务时处理CancellationTokenSource的代码是否正确?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆