【C# .Net】CancellationTokenって必要?

CancellationTokenSource の必要性が分からない…。

Task をキャンセルするサンプルソース
Microsoft 公式のものを少し手直ししたもの

using System.Threading.Tasks;
class Program {
  static void Main() {
    // これ使うのめんどくさくね?
    var cts = new CancellationTokenSource();
    var ct = cts.Token;

    var task = Task.Run(()=>{
      // これ ct がスコープにいないとき受け渡せなくね?
      // 手動で止めるんだったら ct じゃなくてもよくね?
      while (!ct.IsCancellationRequested) { /* 処理 */ }
    });

    // ここから下はわりとどうでもいい
    while (!task.IsCompleted && !task.IsCanceled) {
      Console.WriteLine("処理中…");
      Thread.Sleep(3000);
      cts.Cancel(); // キャンセルしても task が勝手に止まってくれるわけじゃない
    }
    Console.WriteLine("finished");
  }
}

CancellationTokenSource と CancellationToken を使わない方法に置き換えたコード

using System.Threading.Tasks;
class Program {
  static void Main() {
    bool is_canceled = false;
    var task = Task.Run(() => {
      while (is_canceled) { /* 処理 */ }
    });
    while (!task.IsCompleted && !is_canceled) {
      Console.WriteLine("処理中…");
      Thread.Sleep(3000);
      is_caneled = true;
    }
    Console.WriteLine("finished");
  }
}

「bool でいいじゃん」という話。

キャンセラなんとかソース使わないとダメそうなケース

これも Microsoft 公式にあったサンプルソース
そのままコピペしても動かないので、最低限ビルド通るように手直しした

using System.Threading.Tasks;
class Example {
  static CancellationTokenSource cts = new ();
  static TaskFactory factory = new (cts.Token);

  static void Main() {
    var t2 = factory.StartNew(() => DoWork());
    Thread.Sleep(1000);
    cts.Cancel(); // 1秒経過したら問答無用でキャンセル
  }

  static void DoWork() { /* 処理 */ }
}

TaskFactory を使う場合は受け渡しが楽なのと、cts.Cancel() でタスクが止まってくれるので、キャンセラなんたらソースは TaskFactory 用と考えた方が良さそう。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です