もくじ
→https://qiita.com/tera1707/items/4fda73d86eded283ec4f
やりたいこと
下記のようなコードで、Selectを使ってテーブルの値を加工したい。
Selectでテーブル編集.cs
int[] table = { 1,2,3,4,5,6,7,8,9,10 };
private void Button_Click2(object sender, RoutedEventArgs e)
{
var ans = table.Select(x => Add10(x));
}
private int Add10(int a)
{
return a + 10;
}
このとき、Add10メソッドが非同期メソッドだった場合に、どのように書けばよいかわからなかった。
Selectでテーブル編集.cs
int[] table = { 1,2,3,4,5,6,7,8,9,10 };
private async void Button_Click2(object sender, RoutedEventArgs e)
{
// どうやって書けばいい?
// ここでansを計算して、awaitで待って、この後にansを表示させるなどしたい。
var ans = await??? table.Select(async???(x) => ???);
}
private async<int> Add10(int a)
{
// 非同期版の計算メソッド
await Task.Delay(1000);
return a + 10;
}
やりかた
Linqの部分を、Task.WhenAll
で包んで、それをawait
する。
サンプルコード
Selectでテーブル編集(非同期版).cs
int[] table = { 1,2,3,4,5,6,7,8,9,10 };
private async void Button_Click(object sender, RoutedEventArgs e)
{
Debug.WriteLine("処理開始");
// ★★数値tableに100を足す計算をSelectで行い、それをTask.WhenAllで包む★★
var ans = await Task.WhenAll(table.Select(async (x) => await Add100(x)));
Debug.WriteLine($"処理終了");
}
// 100加算して返す(実験的に5秒待つ)
private async Task<int> Add100(int a)
{
Debug.WriteLine($"input is {a}. Start Calc...");
await Task.Delay(1000);
Debug.WriteLine($"input is {a}. End Calc.");
return a + 100;
}
上記を実行すると、下のような出力となる。
処理全体としては、SelectでAdd100メソッドをよぶ処理が10件全部平行して行われるので、1秒(1000ms)経過した時点で処理が完了する。
※1~10までの加算処理の完了は、順番は保証されない。
出力.txt
処理開始
input is 1. Start Calc...
input is 2. Start Calc...
input is 3. Start Calc...
input is 4. Start Calc...
input is 5. Start Calc...
input is 6. Start Calc...
input is 7. Start Calc...
input is 8. Start Calc...
input is 9. Start Calc...
input is 10. Start Calc...
input is 3. End Calc.
input is 2. End Calc.
input is 1. End Calc.
input is 10. End Calc.
input is 8. End Calc.
input is 9. End Calc.
input is 7. End Calc.
input is 6. End Calc.
input is 5. End Calc.
input is 4. End Calc.
処理終了
参考
ラムダ内でasyncを書き、結果はIEnumerable>となるので、配列に戻してやるためにTask.WhenAllとセットで使っていくのが基本となります。
http://neue.cc/2013/12/04_435.html