I'm trying to use Task.ContinueWith
with TaskContinuationOptions.AttachedToParent
to execute a continuation task, e.g.
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?
Edit:
What I'm trying to achieve is a that I want to run a continuation task when outerTask
is completed successfully. I want outerTask
to propagate exceptions from innerTask
to the caller, without having to deal with innerTask
. If outerTask
fails, it should just throw the exception right away (on outerTask.Wait()
without calling innerTask
).
The ContinueWith function is a method available on the task that allows executing code after the task has finished execution. In simple words it allows continuation. Things to note here is that ContinueWith also returns one Task. That means you can attach ContinueWith one task returned by this method.
A continuation task (also known just as a continuation) is an asynchronous task that's invoked by another task, known as the antecedent, when the antecedent finishes.
To start a task in C#, follow any of the below given ways. Use a delegate to start a task. Task t = new Task(delegate { PrintMessage(); }); t. Start();
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:
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..."
"I want to run a continuation task when outerTask is completed successfully"
CiCiting from the last:
For your case, in which there are no parent-child tasks, read Handling Exceptions with 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"
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. I want outerTask to propagate exceptions from innerTask to the caller, without having to deal with innerTask. If outerTask fails, it should just throw the exception right away (on outerTask.Wait() without calling 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). 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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With