C#Taskのタスクキャンセル


Taskタスクのキャンセル
キャンセルタスクはCancellationTokenというトークンを使用します.これはstruct構造体です.コードを見てください.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;

public class Example
{
    public static void Main()
    {
        // Define the cancellation token.
        CancellationTokenSource source1 = new CancellationTokenSource();
        CancellationToken token = source1.Token;

        CancellationTokenSource source2 = new CancellationTokenSource();
        CancellationToken token2 = source2.Token;

        TaskFactory factory = new TaskFactory(token);
        Task tsk1 = factory.StartNew(() =>
        {
            System.Console.WriteLine("This is a new task.");
            Thread.Sleep(5000);
            if(token.IsCancellationRequested)
                token.ThrowIfCancellationRequested();
            
        });

        Thread.Sleep(1000);
        source1.Cancel();
        try
        {
            tsk1.Wait();
        }
        catch (AggregateException ae)
        {
            foreach (Exception e in ae.InnerExceptions)
            {
                if (e is TaskCanceledException)
                    Console.WriteLine("Exception 1 : {0}",
                                      ((TaskCanceledException)e).Message);
                else
                    Console.WriteLine("Exception 2 : " + e.GetType().Name);
            }
        }

        finally
        {
            source1.Dispose();
        }
    }
}

コード実行結果:
This is a new task.
Exception 1 : A task was canceled.

新しいタスクは1秒後(28行)にsource 1オブジェクトのCancel()を呼び出すことでキャンセルタスク操作を開始するが,実際には新しいタスクが5秒後に検出されるため,異常キャンセルタスクの異常情報も5秒後にトリガーされる.つまり、起動キャンセルと実際のキャンセルタスク操作を併用する必要があり、一方の場所ではCancel()が必要であり、他方の場所では対応するトークンを検出する必要があり、最も重要なのはThrowIfCancellationRequested()メソッドを呼び出して異常を投げ出すことであり、この異常動作が本当にタスクをキャンセルすることになる.(そのため、実際には、他の異常を投げ出したり、直接タスクを返したりすることができますが、タスクのキャンセル操作を実現することができます.これは私たち自身のユーザーコードです.マイクロソフトは、CancellationTokenSource、CancellationTokenなどのクラスを使用して、TaskのStatusプロパティと組み合わせることができるソリューションを提供しています.を選択).また、TaskFactoryクラスのオブジェクトは、コンストラクション関数にtokenトークンを入力します.(17行)このトークンオブジェクトは、23行から放出された異常なトークンと同じトークンであるため、TaskCanceledExceptionがキャプチャされる.このときTaskタスクのStatus状態値はCanceledである.また、17行のTaskFactoryクラスコンストラクタでデフォルトコンストラクタを使用してtokenトークンオブジェクトを携帯しなくてもよい.この場合、StartNew()メソッドの2番目のパラメータにはtokenトークンが携帯されており、このトークンとタスクで実際に使用されているトークンが同じトークンであれば、タスクを正常にキャンセルし、タスクステータス修正ビットCanceledを実行できます.トークンが一致しない場合(たとえば17行のtokenがtoken 2に変更された場合)、タスクはキャンセルされることができます(結局、タスクは異常を投げたため本当に終了しました)、ただし、このとき投げ出された異常はOperationCanceledExceptionです.
もう一つ、28行のsource 1をCancel()が18行前(すなわちStartNew()メソッドの前)に移動すると、新しいタスクは実行されません.事前にキャンセルされたためです.この場合、TaskFactoryコンストラクション関数またはStartNew()メソッドがtokenトークンを送信する必要があることが前提です.そうしないと、タスクはキャンセルされません.したがって、TaskFactory()コンストラクション関数またはStartNew()メソッドがtokenトークンに転送するもう一つの機能は、新しいタスクを事前にキャンセルすることができ、このときのタスクのキャンセル速度も十分速い.タスクの最初の文まで実行しないからだ.もう一つの重要なマイクロソフトの参考文献:Task Cancellation