是否有可能“等待等待DoSomethingAsync()”?

内容来源于 Stack Overflow,并遵循CC BY-SA 3.0许可协议进行翻译与使用

  • 回答 (2)
  • 关注 (0)
  • 查看 (24)

常规迭代器块是否与“异步”和“等待”不兼容?

这给了我一个很好的想法,我想要做的是:

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;
}

但是,我收到一个编译器错误,引用“无法从资源加载消息字符串”。

以下是另一次尝试:

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

但是,编译器再次返回一个错误:“无法从资源加载消息字符串”。


下面是我的项目中真正的编程代码

这是非常有用的,当我有一个列表任务,该任务可以从一个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方法。注意代码是如何变成一个简单的一行代码的。每一个网址都开始下载,然后WhenAll将这些操作组合成一个Task

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

tl; dr用yield来实现迭代器是一个阻塞构造,因此现在正在等待并且yield是不兼容的。

Long由于迭代IEnumerable是阻塞操作,因此调用标记为的方法async仍然会以阻塞的方式执行它,因为它必须等待该操作完成。

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

等待Method混合的意义。你是否希望等到Task有一个IEnumerable,然后阻止迭代它?或者你是否在等待每个值IEnumerable

我假设第二个是所需的行为,在这种情况下,现有的Iterator语义将不起作用。该IEnumerator<T>接口基本上是

public interface IEnumerator<T>
  T Current;
  bool MoveNext();
}

Reset()因为它对于一系列异步结果是没有意义的。但是你需要的是这样的:

public interface IAsyncEnumerator<T>
  T Current;
  Task<bool> MoveNext();
}

当然,这foreach也不会起作用,你必须像这样手动迭代:

var moveNext = await asyncEnumerator.MoveNext();
while(moveNext) {

  // get the value that was fetche asynchronously
  var v = asyncEnumerator.Current;

  // do something with that value

  // suspend current execution context until next value arrives or we are done
  moveNext = await asyncEnumerator.MoveNext();
}

所属标签

可能回答问题的人

  • 天使的炫翼

    15 粉丝531 提问35 回答
  • 旺仔小小鹿

    社区 · 运营 (已认证)

    48 粉丝0 提问27 回答
  • 富有想象力的人

    2 粉丝0 提问26 回答
  • 发条丶魔灵1

    6 粉丝525 提问25 回答

扫码关注云+社区

领取腾讯云代金券