Sim*_*mon 8 .net c# asynchronous task-parallel-library async-await
这是这个问题的延续: 多任务延续
我在答案中更改了我的代码,但是现在我在TaskCancelledExceptions尝试运行任务时收到了.
public virtual async Task RunAsync(TaskWithProgress task)
{
Show();
TaskIsRunning();
await SetCompletedHandler(TaskComplete());
await SetCancelledHandler(TaskCancelled())
await SetFaultedHandler(TaskFaulted());
await task;
Close();
}
Run Code Online (Sandbox Code Playgroud)
但是以下代码没有.我有点卡住原因.
public virtual Task RunAsync(TaskWithProgress task)
{
Show();
TaskIsRunning();
SetCompletedHandler(TaskComplete());
SetCancelledHandler(TaskCancelled())
SetFaultedHandler(TaskFaulted());
return task;
}
Run Code Online (Sandbox Code Playgroud)
调用代码基本上涉及以下内容:
await progressDialog.RunAsync(task);
Run Code Online (Sandbox Code Playgroud)
编辑:
我没有取消cancellationtoken任何地方,所以我不明白为什么这会抛出异常.
三个SetXXXHandler()方法基本上执行以下具有不同延续状态的代码:
task.ContinueWith(_ => action(), CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled, this.Scheduler);
Run Code Online (Sandbox Code Playgroud)
堆栈跟踪在这里:
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
Run Code Online (Sandbox Code Playgroud)
Close()只需关闭表格即可.如果我删除该行,则会发生同样的事情.
i3a*_*non 10
你说SetCancelledHandler只是为任务增加了一个延续.我假设相同的任务RunAsync作为参数得到,虽然我无法通过你的代码判断如何SetCancelledHandler继续执行任务(我假设我们缺少一些代码).无论如何...
您在任务完成,取消并出现故障时将运行的任务上注册3个延续.现在让我们假设原始任务成功完成而没有被取消.这意味着你的2个延续(OnCanceled和OnFaulted)将不会运行,因为它们不需要.告诉任务不在其中运行的方法TPL是取消它,这会自动发生.
两个代码片段之间的区别在于,在第一个代码片段中,您await将完成任务,并取消它们以解释您的异常.在第二个片段中,您不等待延续,只是成功运行完成的原始任务.
PS:我认为第二种选择更合适.你不需要await所有那些延续.如果需要,你想让它们运行.
TL; DR:您await取消了继续任务.继续任务,而不是原始任务,是抛出异常的任务.