Task Cancelled Exception (ThrowForNonSuccess)

43,265

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.

Share:
43,265
Simon
Author by

Simon

Technical Coordinator at Fugro TSM, Perth Australia B. Eng Software Engineering Delphi / C# / SQL Server / MySQL Experienced in subsea hardware communications and system development, database admin and creation, experienced radiographer and digital video application development and solutions.

Updated on July 09, 2022

Comments

  • Simon
    Simon almost 2 years

    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.