2

次のサンプルコードがあります。

static class Program
{
    static void Main()
    {
        var cts = new CancellationTokenSource();

        var task = Task.Factory.StartNew(
            () =>
                {
                    try
                    {
                        Console.WriteLine("Task: Running");
                        Thread.Sleep(5000);
                        Console.WriteLine("Task: ThrowIfCancellationRequested");
                        cts.Token.ThrowIfCancellationRequested();
                        Thread.Sleep(2000);
                        Console.WriteLine("Task: Completed");
                    }
                    catch (Exception exception)
                    {
                        Console.WriteLine("Task: " + exception.GetType().Name);
                        throw;
                    }
                }).ContinueWith(t => Console.WriteLine("ContinueWith: cts.IsCancellationRequested = {0}, task.IsCanceled = {1}, task.Exception = {2}", cts.IsCancellationRequested, t.IsCanceled, t.Exception == null ? "null" : t.Exception.GetType().Name));

        Thread.Sleep(1000);

        Console.WriteLine("Main: Cancel");
        cts.Cancel();

        try
        {
            Console.WriteLine("Main: Wait");
            task.Wait();
        }
        catch (Exception exception)
        {
            Console.WriteLine("Main: Catch " + exception.GetType().Name);
        }

        Console.WriteLine("Main: task.IsCanceled = {0}", task.IsCanceled);
        Console.WriteLine("Press any key to exit...");

        Console.ReadLine();
    }
}

出力は次のとおりです。

  • タスク: 実行中
  • メイン:キャンセル
  • メイン:待って
  • タスク: ThrowIfCancellationRequested
  • タスク: OperationCanceledException
  • ContinueWith: cts.IsCancellationRequested = True、task.IsCanceled = False、task.Exception = AggregateException
  • メイン: task.IsCanceled = False
  • 終了するには、任意のキーを押してください...

ContinueWith を削除すると、出力は次のようになります。

  • タスク: 実行中
  • メイン:キャンセル
  • メイン:待って
  • タスク: ThrowIfCancellationRequested
  • タスク: OperationCanceledException
  • メイン: AggregateException をキャッチする
  • メイン: task.IsCanceled = False
  • 終了するには、任意のキーを押してください...

なぜ task.IsCanceled が両方のケースで false を返すのかわかりません。

そして、ContinueWith なしでのみ例外が再スローされるのはなぜですか?


私が達成しようとしているのは、タスクの完了を待つための統一された簡単な方法と、タスクがキャンセルされたかどうかを示すプロパティです。

4

1 に答える 1

6

タスク自体をキャンセルするのではなく、タスクから例外をスローするだけだと思います。StartNew(アクションアクション)の代わりにStartNew(アクションアクション、CancellationTokencancellationToken)を使用してみてください。キャンセルトークンをパラメータとしてContinueWithに追加することもできます。

于 2013-03-13T11:45:46.780 に答える