質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

1回答

2173閲覧

Taskのキャンセル方法について

arw.tyx-out_mz

総合スコア27

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

.NET Framework

.NET Framework は、Microsoft Windowsのオペレーティングシステムのために開発されたソフトウェア開発環境/実行環境です。多くのプログラミング言語をサポートしています。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

1クリップ

投稿2019/07/25 14:35

編集2019/07/25 14:37

前提

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点,わかる方いらっしゃいましたら是非よろしくお願い致します.

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

Delay(TimeSpan, CancellationToken) を使ってください。

A B C には渡さなければいけません。

投稿2019/07/25 14:50

Zuishin

総合スコア28656

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問