简体   繁体   English

Task.ContinueWith和TaskContinuationOptions.AttachedToParent

[英]Task.ContinueWith and TaskContinuationOptions.AttachedToParent

I'm trying to use Task.ContinueWith with TaskContinuationOptions.AttachedToParent to execute a continuation task, eg 我正在尝试将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");

The output from this code is 这段代码的输出是

Outer
Outer done
Inner

but what I expected/try to achieve is 但我期望/试图实现的是

Outer
Inner
Outer done

Is it possible to use AttachedToParent to block an outer task completion, or is AttachedToParent only effective for nested tasks? 是否可以使用AttachedToParent来阻止外部任务完成,或者AttachedToParent仅对嵌套任务有效吗?

Edit: 编辑:

What I'm trying to achieve is a that I want to run a continuation task when outerTask is completed successfully. 我想要实现的是我想在outerTask成功完成时运行一个延续任务。 I want outerTask to propagate exceptions from innerTask to the caller, without having to deal with innerTask . 我希望outerTask将异常从innerTask传播到调用者,而不必处理innerTask If outerTask fails, it should just throw the exception right away (on outerTask.Wait() without calling innerTask ). 如果outerTask失败,它应该立即抛出异常(在outerTask.Wait()而不调用innerTask )。

There are no parent-child tasks in your code. 您的代码中没有父子任务。
You might want to check what is the inner or child task which can be of two types: 您可能想要检查内部或子任务是什么,可以是两种类型:

  • detached child task or nested task , ie parallel task created withing the delegate of another task without a connection to to the task-creator 分离的子任务或嵌套的任务 ,即与另一个任务的委托创建的并行任务,没有与任务创建者的连接
  • attached child task or simply child task , in which case If a child task throws an exception that is otherwise unhandled, it is captured by the parent and rethrown 附加的子任务或简单的子任务 ,在这种情况下,如果子任务抛出一个未处理的异常,它将被父级捕获并重新生成

    Update 更新

    "Is it possible to use AttachedToParent to block an outer task completion..." “是否可以使用AttachedToParent阻止外部任务完成......”

    "I want to run a continuation task when outerTask is completed successfully" “我想在outerTask成功完成时运行一个延续任务”

    CiCiting from the last: CiCiting from last:

    • "A parent task will not finish executing until all of its child tasks have completed, either normally or with exceptions. The parent essentially performs a Wait command for all of its children “父任务在完成所有子任务之前不会完成执行,无论是正常的还是异常的。父级实际上对其所有子级执行Wait命令
    • If a child task throws an exception that is otherwise unhandled, it is captured by the parent and rethrown. 如果子任务抛出一个未处理的异常,则由父级捕获并重新抛出。 It is possible for many child tasks to throw an exception. 许多子任务可能会抛出异常。 All will be combined with any unhandled exception thrown by the parent directly in a single AggregateException." 所有这些都将与父级直接在单个AggregateException中抛出的任何未处理异常相结合。“

For your case, in which there are no parent-child tasks, read Handling Exceptions with Continuations : 对于没有父子任务的情况,请阅读使用Continuations处理异常

"It is important to understand that there is no relationship between antecedents and continuations, except for that which controls scheduling. Specifically, exceptions thrown by a task are not propagated to its linked continuation tasks. This means that you should check for exceptions in all of the tasks that you run. The simplest solution is to wait for all of the tasks that may error to complete and surround the Wait method with a Try / Catch block" “重要的是要理解前提和延续之间没有关系,除了控制调度的情况。特别是,任务抛出的异常不会传播到其链接的延续任务。这意味着你应该检查所有的异常。您运行的任务。最简单的解决方案是等待可能出错的所有任务完成并使用Try / Catch块包围Wait方法“

There are also the code examples of catching-propagating exceptions in the provided by links articles 还有链接文章提供的捕获传播异常的代码示例

Update: 更新:

Edit: 编辑:

What I'm trying to achieve is a that I want to run a continuation task when outerTask is completed successfully. 我想要实现的是我想在outerTask成功完成时运行一个延续任务。 I want outerTask to propagate exceptions from innerTask to the caller, without having to deal with innerTask. 我希望outerTask将异常从innerTask传播到调用者,而不必处理innerTask。 If outerTask fails, it should just throw the exception right away (on outerTask.Wait() without calling innerTask). 如果outerTask失败,它应该立即抛出异常(在outerTask.Wait()上而不调用innerTask)。

Probably, you have already seen the code example from MSDN article Task.ContinueWith Method (Func, CancellationToken, TaskContinuationOptions, TaskScheduler) , which illustrates how to prevent/follow continuation task if antecedent fails/succedes (or vice versa, 4 combinations). 可能你已经看过MSDN文章Task.ContinueWith Method(Func,CancellationToken,TaskContinuationOptions,TaskScheduler)中的代码示例,它说明了如果先行者失败/成功(反之亦然,4种组合)如何阻止/遵循继续任务。 But this is not parent-child, but antecedent-continuation tasks, so there is no containment or linking for exception propagation in either direction. 但这不是父子,而是先行 - 继续任务,因此在任一方向上都没有包含或链接异常传播。

In case of child-parent tasks, it is impossible to prevent child tasks after they have been already launched and only after that a parent failed (or obviously cancel a parent from child). 在子父任务的情况下,在子任务已经启动之后并且仅在父母失败之后(或者显然从子女中取消父母)之后是不可能的。

To achieve what you want, change the line 要实现您想要的效果,请更改线条

outerTask.Wait();

to

innerTask.Wait();

as soon as outertask completes, execution passes the Wait and writes 'Outer done' while the inner task is on Thread.Sleep. 只要outertask完成,执行就会通过Wait并在内部任务在Thread.Sleep上时写入“Outer done”。

The act of adding a continuation to a task will never change when the first task is considered "completed". 当第一个任务被视为“完成”时,向任务添加延续的行为将永远不会改变。 There is no way to force the parent to not be marked as "completed" until all (or even one particular) continuation is run. 在运行所有(甚至一个特定的)延续之前,无法强制父项不被标记为“已完成”。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM