7

我正在尝试使用Task.ContinueWithwithTaskContinuationOptions.AttachedToParent来执行延续任务,例如

Task outerTask = new Task(() => Console.WriteLine("Outer"));
Task innerTask = outerTask.ContinueWith(t =>
    {
        Thread.Sleep(500);
        Console.WriteLine("Inner");
    }, 
    TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion);
outerTask.Start();
outerTask.Wait();
Console.WriteLine("Outer done");

此代码的输出是

Outer
Outer done
Inner

但我期望/试图实现的是

Outer
Inner
Outer done

是否可以用于AttachedToParent阻止外部任务完成,或者AttachedToParent仅对嵌套任务有效?

编辑:

我想要实现的是我想在outerTask成功完成后运行延续任务。我想outerTask将异常传播innerTask给调用者,而不必处理innerTask. 如果outerTask失败,它应该立即抛出异常(outerTask.Wait()不调用innerTask)。

4

3 回答 3

7

您的代码中没有父子任务。
您可能想检查什么是内部或子任务,可以有两种类型:

  • 分离的子任务或嵌套任务,即使用另一个任务的委托创建的并行任务,而不连接到任务创建者
  • 附加的子任务或简单的子任务,在这种情况下,如果子任务抛出一个未处理的异常,它会被父任务捕获并重新抛出

    更新

    “是否可以使用 AttachedToParent 来阻止外部任务完成......”

    “我想在outerTask成功完成后运行一个延续任务”

    CiCiting 从最后:

    • “在其所有子任务完成之前,父任务不会完成执行,无论是正常还是异常。父任务本质上是为其所有子任务执行等待命令
    • 如果一个子任务抛出一个未处理的异常,它会被父任务捕获并重新抛出。许多子任务可能会引发异常。所有这些都将与父级直接在单个 AggregateException 中抛出的任何未处理异常结合在一起。”

对于您没有父子任务的情况,请阅读使用延续处理异常

“重要的是要了解,除了控制调度的关系之外,先行项和延续之间没有关系。具体来说,任务引发的异常不会传播到其链接的延续任务。这意味着您应该检查所有的异常您运行的任务。最简单的解决方案是等待所有可能出错的任务完成并用 Try / Catch 块包围 Wait 方法“

在提供的链接文章中也有捕获传播异常的代码示例

更新:

编辑:

我想要实现的是我想在 outerTask 成功完成时运行延续任务。我希望outerTask 将异常从innerTask 传播到调用者,而不必处理innerTask。如果outerTask 失败,它应该立即抛出异常(在outerTask.Wait() 上而不调用innerTask)。

可能您已经看过 MSDN 文章Task.ContinueWith Method (Func, CancellationToken, TaskContinuationOptions, TaskScheduler)中的代码示例,它说明了如果前件失败/成功(反之亦然,4 种组合)如何防止/遵循继续任务。但这不是父子任务,而是先行延续任务,因此在任一方向上都没有异常传播的遏制或链接。

在子父任务的情况下,不可能在子任务已经启动并且只有在父任务失败(或显然从子任务中取消父任务)之后才能阻止子任务。

于 2013-04-08T18:18:43.740 回答
1

要达到你想要的,换行

outerTask.Wait();

innerTask.Wait();

一旦外部任务完成,执行通过等待并写入“外部完成”,而内部任务在 Thread.Sleep 上。

于 2013-04-08T15:01:05.277 回答
-1

当第一个任务被认为“完成”时,向任务添加延续的行为永远不会改变。在运行所有(甚至一个特定的)延续之前,无法强制父级不被标记为“已完成”。

于 2013-04-08T18:37:20.777 回答