Task
たとえば、タイムアウトが発生した後にキャンセルされる可能性のある s の継続チェーンがあります。キャンセルが発生したときに実行されていたタスクを特定したいと考えています。これが私が話していることです:
CancellationTokenSource cts = new CancellationTokenSource();
Task timeoutTask = Task.Delay(5000).ContinueWith((t) => cts.Cancel());
Task workChain = Task.Factory.StartNew((t) =>
{
Console.WriteLine("Running task " + Task.CurrentId);
Thread.Sleep(1000);
}, -1, cts.Token);
Task parent = workChain;
for (int i = 0; i < 10; i++)
{
parent = parent.ContinueWith((t, o) =>
{
Console.WriteLine("Running task " + Task.CurrentId);
Console.WriteLine("Last Task.AsyncState = " + t.AsyncState);
Thread.Sleep(1000);
}, i, cts.Token, TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Current);
}
parent.ContinueWith((t) =>
{
Console.WriteLine("Cancel task " + Task.CurrentId);
Console.WriteLine("Last running Task.AsyncState = " + t.AsyncState);
}, TaskContinuationOptions.OnlyOnCanceled);
上記を実行すると、渡された前提条件は、OnlyOnCanceled
キャンセルされたときに実行されていたタスクではありません。理由はわかっています。OnlyOnCanceled
タスクは、ループで作成された最後のタスクによって親にされ、タイムアウトが発生すると、完了していないすべてのタスクが開始されずにキャンセルされたものとしてマークされます。
各タスクでトークンの状態を確認し、何かを別の場所に保存することは、ほとんどの場合うまくいきますが、1 つのタスクが完了した後、次のタスクが開始される前にキャンセルが発生する可能性がわずかにあります。その場合、最初にキャンセルされたタスクについては何もわかりません。タスクが開始されたときに何かを保存し、キャンセルされたときに何かを保存することはいつでもできますが、これはすぐにぎこちなく感じ始めます。