これは、この質問の続きです: 複数のタスクの継続
回答のようにコードを変更しましたが、タスクを実行しようとすると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
をどこでもキャンセルしないので、なぜこれがその例外をスローしているのかわかりません。
3つの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つ(OnCanceled
とOnFaulted
)は、実行する必要がないため実行されません。 TPL
で実行しないようにタスクに指示する方法は、タスクをキャンセルすることです。これは自動的に行われます。
2つのコードスニペットの違いは、最初のコードスニペットではタスクの継続をawait
し、それらがキャンセルされて例外を説明することです。 2番目のスニペットでは、継続を待つのではなく、正常に実行されて完了した元のタスクだけを待ちます。
追伸:2番目のオプションの方が適切だと思います。これらすべての継続をawait
する必要はありません。必要に応じて、実行させたいと考えています。
TL; DR:キャンセルされた継続タスクをawait
します。元のタスクではなく、継続タスクが例外をスローします。