実現したいこと
【実現したいこと】
- button1をクリックすると、非同期処理Asyncメソッドが起動され、そこからtaskA、taskB、taskCが非同期で起動されます。
- 3つのタスクが完了した順に戻り値戻り値を確認し、"OK"が含まれていれば残りのタスクをキャンセルしたい。
のですが…
await Task.WhenAny(taskA, taskB, taskC);
はタスクが一つでも終われば、次に進みますし、
await Task.WhenAll(taskA, taskB, taskC);
で待てば確実ですが、一番遅いタスクに引っ張れます。
(正常動作するプログラムも記載しています。)
発生している問題・分からないこと
他の待ち方あるでしょうか?
該当のソースコード
C#
1//正常動作するプログラムです。↓ 2 private void button1_Click(object sender, EventArgs e) 3 { 4 非同期処理Async(); 5 } 6 7 private async void 非同期処理Async() 8 { 9 //キャンセルトークン設定 10 var cts = new CancellationTokenSource(); 11 var token = cts.Token; 12 13 Task<string> taskA = Task.Run(() => _重い処理(5, "1st", token), token); //処理時間5秒 14 Task<string> taskB = Task.Run(() => _重い処理(3, "2nd", token), token); //処理時間3秒 15 Task<string> taskC = Task.Run(() => _重い処理(1, "3rd", token), token); //処理時間1秒 16 17 Console.WriteLine("taskA.Status.ToString();" + taskA.Status.ToString()); 18 Console.WriteLine("taskB.Status.ToString();" + taskB.Status.ToString()); 19 Console.WriteLine("taskC.Status.ToString();" + taskC.Status.ToString()); 20 21 //ひとつでも戻ってきたら終了 22 await Task.WhenAny(taskA, taskB, taskC); 23 24 //残りのTaskをキャンセルする。 25 cts.Cancel(); 26 27 //まとめ 28 Console.WriteLine("taskA:" + taskA.Result); 29 Console.WriteLine("taskB:" + taskB.Result); 30 Console.WriteLine("taskC:" + taskC.Result); 31 } 32 33 34 public string _重い処理(int count, string ID, CancellationToken token) 35 { 36 DateTime now = DateTime.Now; 37 Console.WriteLine("ID:" + ID.ToString() + " ⇒入りました。" + now.ToString() + "/" + now.Millisecond); 38 39 //長大処理の本体(指定秒停止する) 40 for (int i = 0; i <= count - 1; i++) 41 { 42 if (token.IsCancellationRequested) 43 { 44 Console.WriteLine(ID.ToString() + "/キャンセル検知!"); 45 return ID + "/キャンセルされました!"; 46 } 47 48 //長い処理 49 Thread.Sleep(1000); 50 } 51 52 Console.WriteLine(ID + " / 処理完了:" + count.ToString() + "秒間停止しました。"); 53 54 string ans = ""; 55 56 if (ID == "1st") //1stは5秒で完了する。 57 { 58 ans = ID + "/NG"; 59 } 60 else if (ID == "2nd") //2ndは3秒で完了する。 61 { 62 ans = ID + "/OK"; //←ここだけOK!これを待ちたい。 63 } 64 else if (ID == "3rd") //3rdは1秒で完了する。 65 { 66 ans = ID + "/NG"; 67 } 68 69 return ans; 70 }
試したこと・調べたこと
- teratailやGoogle等で検索した
- ソースコードを自分なりに変更した
- 知人に聞いた
- その他
上記の詳細・結果
//ダメだと判りつつ…やっぱりダメなコード
await Task.WhenAny(taskA, taskB, taskC); Console.WriteLine("1回目-------------"); if (taskA.Result.Contains("OK") || taskB.Result.Contains("OK") || taskC.Result.Contains("OK")) { Console.WriteLine("taskA:" + taskA.Result); Console.WriteLine("taskB:" + taskB.Result); Console.WriteLine("taskC:" + taskC.Result); cts.Cancel(); goto SkipPoint; } await Task.WhenAny(taskA, taskB, taskC); Console.WriteLine("2回目-------------"); if (taskA.Result.Contains("OK") || taskB.Result.Contains("OK") || taskC.Result.Contains("OK")) { Console.WriteLine("taskA:" + taskA.Result); Console.WriteLine("taskB:" + taskB.Result); Console.WriteLine("taskC:" + taskC.Result); cts.Cancel(); goto SkipPoint; } await Task.WhenAny(taskA, taskB, taskC); Console.WriteLine("3回目-------------"); if (taskA.Result.Contains("OK") || taskB.Result.Contains("OK") || taskC.Result.Contains("OK")) { Console.WriteLine("taskA:" + taskA.Result); Console.WriteLine("taskB:" + taskB.Result); Console.WriteLine("taskC:" + taskC.Result); cts.Cancel(); goto SkipPoint; } SkipPoint:
補足
特になし

回答3件
あなたの回答
tips
プレビュー
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2025/03/17 03:44