This is a continuation from this question: Multiple Task Continuation
I have changed my code as in the answer, however now I am receiving TaskCancelledExceptions
when I try to run tasks.
public virtual async Task RunAsync(TaskWithProgress task)
{
Show();
TaskIsRunning();
await SetCompletedHandler(TaskComplete());
await SetCancelledHandler(TaskCancelled())
await SetFaultedHandler(TaskFaulted());
await task;
Close();
}
however the following code does not. I am a bit stuck as to why.
public virtual Task RunAsync(TaskWithProgress task)
{
Show();
TaskIsRunning();
SetCompletedHandler(TaskComplete());
SetCancelledHandler(TaskCancelled())
SetFaultedHandler(TaskFaulted());
return task;
}
The calling code basically involves the following:
await progressDialog.RunAsync(task);
Edit:
I do not cancel a cancellationtoken
anywhere so I can't see why this is throwing that exception.
The three SetXXXHandler() methods basically perform the following code with different continuation status:
task.ContinueWith(_ => action(), CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, this.Scheduler);
The Stack trace is here:
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at FugroDXExt.frmBaseProgressAsync.<RunAsync>d__7.MoveNext() in d:\C#\FugroDXExt\trunk\frmBaseProgressAsync.cs:line 92
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.GetResult()
at FCP.Forms.frmProcessing.<mnuApplyCenteredSmoothing_ItemClick>d__34.MoveNext() in d:\C#\FCP\FCP\Forms\frmProcessing.cs:line 578
Close()
simply closes the form. If I remove that line the same thing occurs.
You say that SetCancelledHandler
just adds a continuation to the task. I assume that's the same task RunAsync
gets as a parameter although i can't tell by your code how SetCancelledHandler
gets a task to continue on (I assume we're missing some code). Anyways...
You register 3 continuations on a task that will run when the task completes, is canceled and is faulted. Now let's assume the original task ran to completion successfully without being canceled. That means that 2 of your continuations (OnCanceled
and OnFaulted
) will not run because they don't need to be. The way to tell a task to not run in the TPL
is to cancel it, and that happens automatically.
The difference between your 2 code snippets is that in the first one you await
the task continuations, and they get canceled which explains your exception. On the second snippet you don't await the continuations, just the original task that successfully ran to completion.
P.S: I think the second option is more appropriate. You don't need to await
all those continuations. You want to let them run if they need to.
TL;DR: You await
a canceled continuation task. The continuation task, not the original, is the one that throws an exception.
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