我正在尝试迁移到使用.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。
我们建议在CancellationToken中注册的可取消操作和回调不引发异常。
但是...
立即中断我的处理而不是轮询并仍然遵守框架规定的“规则”的正确方法是什么?
答案 0 :(得分:1)
我可以理解该报价似乎建议不要使用ThrowIfCancellationRequested
,但事实并非如此-使用ThrowIfCancellationRequested
是合适的。
一些表明使用ThrowIfCancellationRequested
的消息来源是合适的:
乔恩·斯基特(Jon Skeet)的SO answer表示ThrowIfCancellationRequested
是正确的方法。
抛出
OperationCanceledException
是TPL中“您调用的方法被取消”的惯用方式。不要与之抗争-只是期待而已。
此Microsoft source
表示ThrowIfCancellationRequested
是正确的方法。
成功的取消涉及请求代码,该代码调用CancellationTokenSource.Cancel方法,并且用户委托及时终止操作。您可以使用以下选项之一终止操作:
- 只需从代表处返回[此项目符号的其余部分]
- 通过抛出OperationCanceledException并将需要取消的令牌传递给它。执行此操作的首选方法是使用ThrowIfCancellationRequested方法。以这种方式取消的任务会转换为已取消状态,调用代码可以使用该状态来验证任务是否响应了其取消请求
还有一个代码示例,演示如何正确使用ThrowIfCancellationRequested
。
进一步引用此Microsoft资料的另一句话:
当任务实例观察到用户代码引发的OperationCanceledException时,任务会将其解释为确认取消并转换为Canceled状态。
...
还请注意,其他异常的存在也会导致任务转换为故障状态...