web-dev-qa-db-ja.com

CancellationTokenをタスククラスコンストラクターに渡すことの用途は何ですか?

これは、長時間実行されるプロセスをシミュレートする新しいタスクを作成するサンプルコードです。そのようなタスクにはあまり何もありません、そして純粋にキャンセル機能に焦点を合わせます。キャンセルトークンを使用してタスクをキャンセルしていますが、コードは正常に機能します。

CancellationTokenSource CTS = new CancellationTokenSource();

Task<Boolean> PTask = new Task<Boolean>(() => 
{
   while (true)
   {
       if (!CTS.Token.IsCancellationRequested)
       {
          Thread.Sleep(5000);
       }
       else { Console.WriteLine("Thread Cancelled");break; }
   }
   return true;

}, CTS.Token, TaskCreationOptions.None);

PTask.Start();
Console.WriteLine("Hit Enter to cancel the Secondary thread you have started");
Console.ReadLine();
CTS.Cancel();
System.Console.WriteLine(PTask.Result);

しかし、私が理解できなかったことの1つは、トークンパラメーター(CTS.TokenTaskコンストラクターに渡されます。コンストラクターにトークンを渡さなくても実際にタスクをキャンセルできる場合、パラメーターを渡すことの実際の使用法は何ですか。

以下は、トークンパラメータなしで機能するわずかに変更されたバージョンです。

CancellationTokenSource CTS = new CancellationTokenSource();
Task<Boolean> PTask = new Task<Boolean>(() => 
{
   while (true)
   {
       if (!CTS.Token.IsCancellationRequested)
       {
           Thread.Sleep(5000);
       }
       else
       {
           Console.WriteLine("Thread Cancelled");
           break;
       }
};
21
Prabhu Murthy

更新:次の msdn 質問は理由を説明しています:

トークンをStartNewに渡すと、トークンがタスクに関連付けられます。これには2つの主な利点があります。

  1. タスクの実行を開始する前にトークンにキャンセルが要求された場合、タスクは実行されません。 [実行中]に移行するのではなく、すぐに[キャンセル済み]に移行します。これにより、実行中にタスクがキャンセルされた場合のタスクの実行コストを回避できます。

  2. タスクの本体もキャンセルトークンを監視していて、そのトークンを含むOperationCanceledExceptionをスローする場合(これはThrowIfCancellationRequestedが行うことです)、タスクがそのOCEを検出すると、OCEのトークンがタスクのトークンと一致するかどうかを確認します。 。含まれている場合、その例外は協調キャンセルの確認応答と見なされ、タスクは(障害状態ではなく)キャンセル状態に移行します。

38
daryal