1. ホーム
  2. c#

[解決済み] await yield return DoSomethingAsync()」は可能か?

2022-07-23 22:02:45

質問

通常のイテレータブロック (すなわち "yield return") は "async" および "await" と互換性がないのでしょうか?

これは、私がやろうとしていることの良いアイデアを与えてくれます。

async Task<IEnumerable<Foo>> Method(String [] Strs)
{
    // I want to compose the single result to the final result, so I use the SelectMany
    var finalResult = UrlStrings.SelectMany(link =>   //i have an Urlstring Collection 
                   await UrlString.DownLoadHtmlAsync()  //download single result; DownLoadHtmlAsync method will Download the url's html code 
              );
     return finalResult;
}

しかし、私は "unable to load message string from resources" を引用したコンパイラーエラーを得ました。

以下は別の試みです。

async Task<IEnumerable<Foo>> Method(String [] Strs)
{
    foreach(var str in strs)
    {
        yield return await DoSomethingAsync( str)
    }
}

しかし、再びコンパイラはエラーを返します: "unable to load message string from resources".


以下は、私のプロジェクトにおける実際のプログラミングコードです。

これは、URLからHTMLをダウンロードするタスクであるリストタスクがある場合に非常に便利です。 という構文を使用した場合、結果として IEnumerable<Foo> . このようなコードは書きたくありません。

async Task<IEnumerable<String>> DownLoadAllURL(String [] Strs)
{
    List<Foo> htmls= new ...
    foreach(var str in strs)
    {
        var html= await DownLoadHtmlAsync( str)
        htmls.Add(item)
    }
    return htmls;
}

でも、そうせざるを得ないようです。

何かとお世話になります。

どのように解決するのですか?

説明されていることは Task.WhenAll メソッドで実現できます。コードがどのように単純なワンライナーに変わるかに注目してください。何が起こるかというと、個々の url がダウンロードを開始し、次に WhenAll がこれらの操作をひとつにまとめるために使われます。 Task にまとめ、待ち受けることができます。

Task<IEnumerable<string>> DownLoadAllUrls(string[] urls)
{
    return Task.WhenAll(from url in urls select DownloadHtmlAsync(url));
}