C# 多源任务取消

C# 多源任务取消,c#,.net,task,task-parallel-library,cancellation,C#,.net,Task,Task Parallel Library,Cancellation,我目前有一个应用程序,其中我创建了一系列任务,这些任务一个接一个地执行,其中的取消源可以中断任务之间的执行(即在安全终止点)。我目前仅在管理类被释放时使用此取消源,作为一种干净快速地中止执行的方法 我现在有一个用例,我想创建一个自动超时来取消任务序列,以防操作员没有及时响应(一些任务等待操作员与物理机制的交互)。同时,如果管理类被释放,我仍然需要支持取消。我发现,这听起来像是我需要的,但我有几个顾虑: 多个任务系列可以并行执行,因此我需要为超时取消创建一个新的CancellationTokenS

我目前有一个应用程序,其中我创建了一系列任务,这些任务一个接一个地执行,其中的取消源可以中断任务之间的执行(即在安全终止点)。我目前仅在管理类被释放时使用此取消源,作为一种干净快速地中止执行的方法

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

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

  • 我还需要防止在计时器过期之前释放取消源的情况(因此我不取消已释放的源)。这是一种潜在的竞争情况,因此我需要添加适当的锁定。这看起来也很尴尬,增加了很大的复杂性(未来的维护成本),并使单元测试更具挑战性(竞争条件很难可靠地诱导)


  • 我在这里走的是正确的道路,还是有更简单的方法来实现这一点?

    您问题中的核心问题似乎与调用
    任务
    和/或
    取消令牌源
    对象上的
    Dispose()
    有关。在这种情况下,我建议不要对这些调用
    Dispose
    ,这将大大简化您的设计

    作为理由,我会让你参考。Stephen Toub(负责任务的PM)特别建议您:

    如果根据代码的结构可以轻松正确地进行处理,则应积极处理。如果为了处理而开始执行奇怪的旋转(或者对于任务,使用额外的同步来确保处理是安全的,因为只有在任务完成后才能使用Dispose),那么最好依靠终结来处理事情


    这听起来像是他在最后描述的确切情况——你试图做奇怪的旋转,以便在这些对象上调用
    Dispose()

    我有一个强烈的想法,就是我应该总是在IDisposable对象上调用Dispose,所以即使得到Stephen Toub的祝福,我也不愿意这样做。事实上,
    CancellationTokenSource.Dispose()
    的MSDN文档特别指出,您应该始终调用Dispose();这可能只是泛泛而谈,但这表明.NET团队没有合同义务将Dispose()保留为此类的“可选”@Dan:我知道-但是,记住,任何正确实现的
    IDisposable
    对象如果不调用
    Dispose()
    ,都会被终结器“清理”。我觉得您应该总是尝试调用任何
    IDisposable
    对象上的
    Dispose()
    ,但是,在某些情况下,您让您的生活变得比将它留给终结器更糟糕。TPL是事情变得模糊的领域之一——通常(依我看)最好不要
    Dispose()
    TPL对象,因为这样做所需的工作很可能会带来维护问题和bug。我完全明白你的观点(从实际角度看,完成工作)这可能就是我最终要做的,但这些“两害相权取其轻”的情况让我感到厌烦。然而,在这一点上,反对意见更多的是哲学上的,而不是技术上的,这是任何工程都不可能解决的。@Dan:我知道你的意思——不“故意”处理某些东西会让我感到不安——但归根结底,这是比邪恶小得多的东西。。。。