【问题标题】:How to cancel a bunch of tasks when any of these tasks throws an exception?当这些任务中的任何一个引发异常时,如何取消一堆任务?
【发布时间】:2012-11-02 14:24:41
【问题描述】:

我创建并启动了许多任务。 其中一项任务可能会引发异常。如果发生这种情况,我需要停止所有任务。

现在我只看到唯一的方法是将 CancellationTokenSource 传递给每个任务并在 catch 块中调用 Cancel()。

TPL 是否以更通用的方式支持所需的功能?

类似:

Action<Task> onExceptionAction = t => cancellationTokenSource.Cancel();
var task = Task.WhenAnyThrows<MyException>(tasks, onExceptionAction);

如果没有抛出异常,则认为任务完成(或取消)

【问题讨论】:

  • 在我看来,取消支持非常通用。您只需要一个CancellationTokenSource 即可传递给所有任务。您只需在该令牌上调用一次Cancel 即可取消所有使用它的任务。对我来说似乎很笼统。
  • 嗯,没关系,但是如果你有一些任务制作人呢?您从它那里收到带有关联 CancellationTokenSource 的可取消任务。在这种情况下,您无法控制此任务中的异常处理。您可以使用调用 CreateLinkedTokenSource 方法创建的链接 CTS 取消此任务。不过,您不能在任务中嵌入取消操作。是的,这个例子有点人为但似是而非。

标签: .net multithreading task-parallel-library


【解决方案1】:

如果我理解正确,你想要的是ContinueWith()TaskContinuationOptions.OnlyOnFaulted

因此,您的方法可能如下所示:

void CancelWhenAnyFaults(IEnumerable<Task> tasks, CancellationTokenSource cts)
{
    foreach (var task in tasks)
        task.ContinueWith(
            _ => cts.Cancel(), cts.Token, TaskContinuationOptions.OnlyOnFaulted,
            TaskScheduler.Current);
}

我也将CancellationToken 传递给ContinueWith(),这样当一个任务失败时,不会执行其他延续。

【讨论】:

  • 为什么 OnlyOnFaulted 我会认为 NotOnFaulted 或 NotOnCancelled ?
  • @Blam 当Task 出现故障时,您想做某事(取消令牌),这就是OnlyOnFaulted 的原因。
猜你喜欢
  • 1970-01-01
  • 2011-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-12-30
  • 1970-01-01
  • 2022-07-11
相关资源
最近更新 更多