私はCancellationToken/CancellationTokenSourceシステムがC++ volatile bool bFlagCancelled
のような働きをしていると考えました。これは、キャンセルは自発的にタスクの部分で行われ、タスク自体が随時チェックされてキャンセルされ、例外がスローされるかどうかを確認します明示的に、またはThrowIfCancellationRequested()
を呼び出してキャンセルされていないかどうかをチェックしないTPLタスクは引き続きキャンセルできますか?
StartNew()
の直後にキャンセルを呼び出すと、タスクが停止し、を呼び出すとTaskCanceledException
がスローされます。例えば
、このコード:
CancellationTokenSource source = new CancellationTokenSource();
CancellationToken token = source.Token;
Task task = Task.Factory.StartNew(
() =>
{
Console.WriteLine("start sleep");
Thread.Sleep(1000);
Console.WriteLine("sleep ended");
}
, token);
// Thread.Sleep(1);
source.Cancel();
Console.WriteLine("start wait");
task.Wait();
Console.WriteLine("wait ended");
私はこの出力を得る:
start wait Exception: System.AggregateException: One or more errors occurred. ---> System.Threading.Tasks.TaskCanceledException: A task was canceled.
しかし、私は// Thread.Sleep(1);
のコメントを外した場合、その後の動作の変更と、私はこの出力を得る:
start sleep start wait sleep ended wait ended
これはおそらくtask.Start()
がまだ呼び出されていないためです私が理解する限り、StartNew()
はtask.Start()
を呼び出してから返送されます。そのため、同期コストがなく、new Task
を作成してtask.Start()
を作成することをお勧めします。
この場合、キャンセルトークンを確認しなくても、タスクが自動的にキャンセルされることがあります。これが起こる唯一の状況ですか、これが起こるより多くのシナリオがありますか?
答えをありがとう。これが起こる可能性がある他の状況はありますか、これは唯一のものですか? – sashoalm
@sashoalmタスクがまだ「実行中」に遷移していないときはいつでも。たとえば、タスクで 'ContinueWith'を呼び出してこのタスクをキャンセルすると、継続もキャンセルされます –
もう一度ありがとうございます。私はちょうどhttp://stackoverflow.com/a/10444108/492336を見つけました。ここで、 'StartNew'に' token'を渡すことは、特にこの動作を有効にすることであり、本当に 'StartNew()'にトークンを渡さないことが説明されています。 '// Sleep(1)'のコメントを解除するのと同じ効果があります。 – sashoalm