10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[C#] Linqの中でawaitさせたいとき

Last updated at Posted at 2019-10-23

もくじ
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

10
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
10
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?