任务取消exception(ThrowForNonSuccess)

这是这个问题的延续: 多任务延续

我在答案中更改了我的代码,但是现在我在尝试运行任务时收到TaskCancelledExceptions

 public virtual async Task RunAsync(TaskWithProgress task) { Show(); TaskIsRunning(); await SetCompletedHandler(TaskComplete()); await SetCancelledHandler(TaskCancelled()) await SetFaultedHandler(TaskFaulted()); await task; Close(); } 

但是以下代码没有。 我有点卡住为什么。

 public virtual Task RunAsync(TaskWithProgress task) { Show(); TaskIsRunning(); SetCompletedHandler(TaskComplete()); SetCancelledHandler(TaskCancelled()) SetFaultedHandler(TaskFaulted()); return task; } 

调用代码基本上涉及以下内容:

 await progressDialog.RunAsync(task); 

编辑:

我没有在任何地方取消cancellationtoken ,所以我不明白为什么这会抛出exception。

三个SetXXXHandler()方法基本上执行以下具有不同延续状态的代码:

 task.ContinueWith(_ => action(), CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, this.Scheduler); 

堆栈跟踪在这里:

  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.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.d__34.MoveNext() in d:\C#\FCP\FCP\Forms\frmProcessing.cs:line 578 

Close()只是关闭表单。 如果我删除该行,则会发生同样的事情。

你说SetCancelledHandler只是为任务添加了一个延续。 我假设RunAsync作为参数获得了相同的任务,尽管我无法通过您的代码告诉SetCancelledHandler如何继续执行任务(我假设我们缺少一些代码)。 无论如何…

您在任务完成,取消并出现故障时将运行的任务上注册3个延续。 现在让我们假设原始任务成功完成而没有被取消。 这意味着你的2个延续( OnCanceledOnFaulted )将不会运行,因为它们不需要。 告诉任务不在TPL运行的方法是取消它,这会自动发生。

你的两个代码片段之间的区别在于,在第一个代码片段中await任务延续,它们会被取消,这解释了你的exception。 在第二个片段中,您不会等待延续,只是成功运行完成的原始任务。

PS:我认为第二种选择更合适。 您无需await所有这些延续。 如果需要,你想让它们运行。

TL; DR: await取消的继续任务。 继续任务,而不是原始任务,是抛出exception的任务。