参考サイト
ポイント
CancellationTokenSource() でトークン作成して、トークンからキャンセル用トークンを生成して、それをすべての非同期タスクで共有して、キャンセルが起きた時の処理をタスクに書くってとこ。
今回は WaitKeyTask でしかキャンセルしてないけど、すべてのタスクで共有して、WaitKeyTaskともども Task.WaitAll() で待っておけば、どこからでもキャンセルできるようになると思う。
コード
using System; using System.Threading; using System.Threading.Tasks; using System.Collections.Generic; namespace ExampleOfWaitKey { class Program { static void Task1(CancellationToken token, string c, int duration) { while (true) { Console.Write(c); Task.Delay(duration).Wait(); if(token.IsCancellationRequested) { // WaitKeyTask() でキャンセルが発行されると // Task.Delay().Wait() 明けにこちらに落ちる // 終了に時間がかかるような処理の代わり var t = new Random().Next(1,10); Task.Delay(t * 100).Wait(); Console.WriteLine(); Console.WriteLine("{0}: was canceled", c); return; } } } static void WaitKeyTask(CancellationTokenSource tokenSource) { Console.ReadLine(); // キー入力まち tokenSource.Cancel(); // キャンセル通知 } static void Main(string[] args) { // キャンセル伝播用トークンの作成 var tokenSource = new CancellationTokenSource(); var cancelToken = tokenSource.Token; // キー入力待ち非同期タスクの実行 var waitKeyTask = Task.Run(() =>WaitKeyTask(tokenSource)); // 非同期処理タスクの実行 // var tasks = new List<Task>(); tasks.Add(Task.Run(() => Task1(cancelToken, "a", 100))); tasks.Add(Task.Run(() => Task1(cancelToken, "b", 200))); // キー入力待ち waitKeyTask.Wait(); Console.WriteLine(); Console.WriteLine("キーが押されました。"); Console.WriteLine("すべてのタスクが終了するのを待ちます..."); // 全タスクのキャンセル処理待ち Task.WaitAll(tasks.ToArray()); } } }