前提
C#でTaskを使用して非同期処理を行っております.
Taskの外からのキャンセル方法について,疑問が出ましたので投稿させてください.
疑問点
いろいろWebで調べてみた結果,CancellationToken
を使用するやり方が正しいということはわかりました.
このCancellationToken
を実行中のTaskに渡し,IsCancellationRequested
を中でチェックするという例が多く見つかりましたが,Web上のサンプルは非常にシンプルな構成となっており,以下の2つの疑問点が解消されませんでした.
①Delayなどをキャンセルする場合
Web上のサンプルの多くは,while
ループなどを回し,その中で繰り返しIsCancellationRequested
を確認していました.
しかし,Task.Delay
のように決まった秒数止まって欲しいTask(例えば5秒待ってとか)でも,途中でキャンセルすることを考えるのであれば,while
ループで秒数を少分割して,小刻みにキャンセル状態をチェックするしかないのでしょうか.
以下のような感じです.
C#
1async Task Hoge() 2{ 3 // 5秒待って欲しい 4 await Task.Delay(5000); 5} 6↓↓↓ 7async Task Hoge(CancellationToken token) 8{ 9 // 5000msを50msに分割する 10 int sum = 0; 11 while (sum <= 5000) 12 { 13 await Task.Delay(50); 14 sum += 50; 15 if (token.IsCancellationRequested) 16 break; 17 } 18}
②メソッドへのTokenの受け渡しについて
調べていたときに出てきた例では,大抵1つのメソッドのみを非同期にしていたので,Token
を渡すことに対してなにも違和感は覚えなかったのですが,以下のように複数のメソッドを1つのメソッドにまとめている場合,再帰的に全てのメソッドに対してToken
を渡さなければいけないのでしょうか.
C#
1async Task Execute() 2{ 3 var tokenSource = new CancellationTokenSource(); 4 var token = tokenSource.Token; 5 await Task.Run(() => DoAll(token)); 6} 7 8void DoAll(CancellationToken token) 9{ 10 // 同期処理を順次実行 11 A(token); 12 B(token); 13 C(token); 14} 15 16void A(CancellationToken token) 17{ 18 // 同期的な遅い処理 19} 20 21void B(CancellationToken token) 22{ 23 // 同期的な遅い処理 24} 25 26void C(CancellationToken token) 27{ 28 // 同期的な遅い処理 29}
上のコードのようにTask.Run
で呼び出される可能性があり,かつ途中でキャンセルしたいメソッド全てにCancellationToken
を渡さないといけないのでしょうか.
仮にそうだとしたら相当めんどうな気がします.
そういうものなんでしょうか.
また,少し本題とはずれてしまいますが,同期メソッドにCancellationToken
を渡しているのが少し違和感なのですが,これは普通なのでしょうか.
上記2点,わかる方いらっしゃいましたら是非よろしくお願い致します.

回答1件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2019/07/26 09:11