10

タスク内でCancellationTokenSource.Cancel()メソッドを呼び出してTask <>をキャンセルしようとしていますが、機能させることができません。

これが私が使用しているコードです:

TaskScheduler ts = TaskScheduler.Current;

CancellationTokenSource cts = new CancellationTokenSource();

Task t = new Task( () =>
{
    Console.WriteLine( "In Task" );
    cts.Cancel();
}, cts.Token );

Task c1 = t.ContinueWith( antecedent =>
{
    Console.WriteLine( "In ContinueWith 1" );
}, CancellationToken.None, TaskContinuationOptions.OnlyOnRanToCompletion, ts );

Task c2 = c1.ContinueWith( antecedent =>
{
    Console.WriteLine( "In ContinueWith 2" );
}, TaskContinuationOptions.NotOnCanceled );

t.Start();

Console.ReadKey();

Environment.Exit( 1 );

このプリントアウト:

In Task
In ContinueWith 1
In ContinueWith 2

私が期待したのはこれでした:

In Task

ここで何かが足りませんか?タスクはタスク外でのみキャンセルできますか?

4

2 に答える 2

10

タスクは、次の場合にのみ「キャンセル」されたと見なされます

  • そのキャンセルトークンは、実行を開始する前にキャンセルされます。
  • そのキャンセルトークンは実行中にキャンセルされ、コードはOperationCancelledExceptionをスローすることによって(通常はコード呼び出しによってcts.Token.ThrowIfCancellationRequested())キャンセルを協調的に監視します。

cts.Token.ThrowIfCancellationRequested()その後に行を追加するcts.Cancel()と、期待どおりに動作します。あなたの例では、キャンセルはタスクの実行中に行われますが、タスクはキャンセルを監視せず、タスクのアクションは完了するまで実行されます。そのため、タスクは「RantoCompletion」としてマークされます。

継続()内のキャンセルトークンをチェックすることにより、「完了まで実行」されたが(タスクの完了中または完了後に)キャンセルされたタスクのケースを確認できますcts.Token.IsCancellationRequested。時々役立つ別のオプションは、元のキャンセルトークンを継続のキャンセルトークンとして使用することです(そうすれば、キャンセルが先行タスクによって認識されない場合、少なくとも継続によって尊重されます)-TPL実行する前に、継続をキャンセル済みとしてマークします。

于 2012-11-12T14:52:45.910 に答える
0

このスニペットは期待どおりに機能します。

var cts = new CancellationTokenSource();

            var t = new Task(() =>
            {
                Console.WriteLine("In Task");
                cts.Cancel();
            }, cts.Token);

            Task c1 = t.ContinueWith(antecedent =>
            {
                Console.WriteLine("In ContinueWith 1");
            }, CancellationToken.None, TaskContinuationOptions.OnlyOnCanceled/* by definition from MSDN here must be NotOnCanceled*/, TaskScheduler.Current);

            c1.ContinueWith(antecedent =>
            {
                Console.WriteLine("In ContinueWith 2");
            }, TaskContinuationOptions.NotOnCanceled);

            t.Start();
            Console.ReadKey();

            Environment.Exit(1);

TaskContinuationOptionsしかし、列挙型にはバグがあるようです。

NotOnCanceled先行タスクがキャンセルされた場合に、継続タスクをスケジュールしないように指定します。このオプションは、マルチタスクの継続には無効です。

OnlyOnCanceled先行タスクがキャンセルされた場合にのみ、継続タスクをスケジュールする必要があることを指定します。このオプションは、マルチタスクの継続には無効です。

于 2012-11-12T13:53:29.883 に答える