c# - 任务取消异常 (ThrowForNonSuccess)

标签 c# .net asynchronous task-parallel-library async-await

这是这个问题的延续: Multiple Task Continuation

我已经按照答案更改了我的代码,但是现在我在尝试运行任务时收到 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,所以我不明白为什么会抛出异常。

三个 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.<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() 只是关闭表单。如果我删除该行,则会发生同样的事情。

最佳答案

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

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

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

P.S:我觉得第二种更合适。您不需要 await 所有这些延续。如果需要,您想让它们运行。

TL;DR:您await 一个已取消的延续任务。继续任务,而不是原始任务,是抛出异常的任务。

关于c# - 任务取消异常 (ThrowForNonSuccess),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21190552/

相关文章:

c# - 如何设置 NLOG 使用多个数据库

c# - 如果类是 WinRT 类型,如何使用 C# 反射来确定

c# - 奇怪的继承修改

c# - 无法监视 Azure 中的自定义性能计数器

.net 3.5 : To read connectionstring from app. 配置?

c# - 如何在 WCF 服务中使用 RequestContext 映射路径

java - Python 通过异步递增变量运行 Java 命令行参数。

c++ - 嵌套 Lambda 函数 - 性能影响

javascript - 异步 ajax 调用无需 async=false 并在每次调用之间设置延迟

c# - WPF DatePicker 在更改月份时抛出异常