具有多个来源的任务取消

时间:2011-06-07 17:13:23

标签: c# .net task task-parallel-library cancellation

我目前有一个应用程序,我创建了一系列一个接一个地执行的任务,其中一个取消源可以中断任务之间的执行(即在安全终止点。)我目前只在管理时使用此取消源class是Disposed,是一种干净利落地快速中止执行的方法。

我现在有一个用例,我想创建一个自动超时来取消任务序列,以防操作员没有及时响应(某些任务等待操作员与物理机制的交互) 。)同时,如果管理类是Disposed,我仍然需要支持取消。我找到CancellationTokenSource.CreateLinkedTokenSource,这听起来像我需要的,但我有一些担忧:

  1. 多个任务系列可以并行执行,因此我需要创建一个新的CancellationTokenSource用于超时取消,并为我开始的每个任务系列创建一个关联的链接源。 CancellationTokenSource实现IDisposable,这意味着我需要保留两个取消源并在最后一个任务完成时或任何子任务被取消或出现故障时处理它们。这似乎相当尴尬,即使有匿名方法闭包的有用魔法(仍然传递这些取消源。)

  2. 我还需要在计时器到期之前防止取消源处理的情况(因此我不取消已处置的源。)这是潜在的竞争条件,所以我需要添加适当的锁定。这似乎也很尴尬,增加了显着的复杂性(未来的维护成本),并使单元测试更具挑战性(竞争条件难以可靠地诱导。)

  3. 我是在这里走正确的道路还是有更简单的方法来做到这一点?

1 个答案:

答案 0 :(得分:9)

您的问题中的核心问题似乎与您在Dispose()和/或Task个对象上调用CancellationTokenSource有关。在这种情况下,我建议只是在这些上调用Dispose,这应该会大大简化您的设计。

作为理由,我会将您推荐给this thread。特别是,Stephen Toub(负责任务的PM)建议你应该:

  

积极配置如果根据您的代码结构轻松正确地执行操作。如果您开始为了Dispose而进行奇怪的旋转(或者在任务的情况下,使用额外的同步以确保它可以安全处置,因为Dispose可能只在任务完成时使用),所以最好依靠完成照顾好事情。

这听起来像他最后描述的确切情况 - 你正试图做一些奇怪的旋转,以便在这些物体上召唤Dispose()