Task.ContinueWith和TaskContinuationOptions.AttachedToParent

lar*_*moa 7 .net c# task-parallel-library

我试图使用Task.ContinueWithTaskContinuationOptions.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");
Run Code Online (Sandbox Code Playgroud)

这段代码的输出是

Outer
Outer done
Inner
Run Code Online (Sandbox Code Playgroud)

但我期望/试图实现的是

Outer
Inner
Outer done
Run Code Online (Sandbox Code Playgroud)

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

编辑:

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

Gen*_*нин 7

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

  • 分离的子任务或嵌套的任务,即与另一个任务的委托创建的并行任务,没有与任务创建者的连接
  • 附加的子任务或简单的子任务,在这种情况下,如果子任务抛出一个未处理的异常,它将被父级捕获并重新生成

    更新

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

    "我想在outerTask成功完成时运行一个延续任务"

    CiCiting from last:

    • "父任务在完成所有子任务之前不会完成执行,无论是正常的还是异常的.父级实际上对其所有子级执行Wait命令
    • 如果子任务抛出一个未处理的异常,则由父级捕获并重新抛出.许多子任务可能会抛出异常.所有这些都将与父级直接在单个AggregateException中抛出的任何未处理异常相结合."

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

"重要的是要理解前提和延续之间没有关系,除了控制调度的情况.特别是,任务抛出的异常不会传播到其链接的延续任务.这意味着你应该检查所有的异常.您运行的任务.最简单的解决方案是等待可能出错的所有任务完成并使用Try/Catch块包围Wait方法"

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

更新:

编辑:

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

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

在子父任务的情况下,在子任务已经启动之后并且仅在父母失败之后(或者显然从子女中取消父母)之后是不可能的.