通过在注册回调中调用ThrowIfCancellationRequested对取消请求做出反应

时间:2019-08-27 09:57:25

标签: c# task cancellation cancellationtokensource cancellation-token

我正在尝试迁移到使用.NET中的CancellationToken / Src构造,例如:https://docs.microsoft.com/en-us/dotnet/standard/threading/cancellation-in-managed-threads

我的基本问题是关于对取消请求的反应。

就我而言,我进行了一些长时间运行的处理,这对于保持一致性并不重要。当取消请求到达时,我无法承担“轮询”的模式,例如:

        while (!_token.IsCancellationRequested)
        {
            DoProcessing(...)
        }

因为处理过程可能需要几分钟,所以我真的想立即退出。

我的问题是,是否正确的方法就是简单地使用此设置:

    public void Start()
    {
        _token.Register(() => _token.ThrowIfCancellationRequested());

        // Continuously process stuff.
        while (!_token.IsCancellationRequested)
        {
            DoProcessing(...)
        }
    }

也就是说,注册一个回调,该回调又会引发OperationCanceledException。

我可以在这里阅读:https://docs.microsoft.com/en-us/dotnet/api/system.threading.cancellationtokensource.cancel?view=netframework-4.8,即:

  

我们建议在CancellationToken中注册的可取消操作和回调不引发异常。

但是...

立即中断我的处理而不是轮询并仍然遵守框架规定的“规则”的正确方法是什么?

1 个答案:

答案 0 :(得分:1)

我可以理解该报价似乎建议不要使用ThrowIfCancellationRequested,但事实并非如此-使用ThrowIfCancellationRequested是合适的。

一些表明使用ThrowIfCancellationRequested的消息来源是合适的:

乔恩·斯基特(Jon Skeet)的SO answer表示ThrowIfCancellationRequested是正确的方法。

  

抛出OperationCanceledException是TPL中“您调用的方法被取消”的惯用方式。不要与之抗争-只是期待而已。

Microsoft source 表示ThrowIfCancellationRequested是正确的方法。

  

成功的取消涉及请求代码,该代码调用CancellationTokenSource.Cancel方法,并且用户委托及时终止操作。您可以使用以下选项之一终止操作:

     
      
  • 只需从代表处返回[此项目符号的其余部分]
  •   
  • 通过抛出OperationCanceledException并将需要取消的令牌传递给它。执行此操作的首选方法是使用ThrowIfCancellationRequested方法。以这种方式取消的任务会转换为已取消状态,调用代码可以使用该状态来验证任务是否响应了其取消请求
  •   

还有一个代码示例,演示如何正确使用ThrowIfCancellationRequested

进一步引用此Microsoft资料的另一句话:

  

当任务实例观察到用户代码引发的OperationCanceledException时,任务会将其解释为确认取消并转换为Canceled状态。

     

...

     

还请注意,其他异常的存在也会导致任务转换为故障状态...

  • 我怀疑(这只是我试图调和这两个来源),这就是您引用的建议所指的-这是为了避免破坏取消机制准确指示任务状态为已取消或取消的能力的建议。错误的