将异步循环转换为LINQ查询

Jay*_*uzi 6 c# linq async-await

我有这个简单的循环,我想使用LINQ以声明方式编写.

    async Task<Foo> GetFooAsync(string fooId, CancellationToken cancellationToken = default(CancellationToken))
    {
        foreach (var source in FooSources)
        {
            var result = await source.GetFooAsync(fooId, cancellationToken).ConfigureAwait(continueOnCapturedContext: false);
            if (result != null)
            {
                return result;
            }
        }
        return null;
    }
Run Code Online (Sandbox Code Playgroud)

我希望看起来像:

return FooSources.Where(...).FirstOrDefault();
Run Code Online (Sandbox Code Playgroud)

我被困住了,特别是在制作LINQ和async/ await一起工作时.

Ste*_*ary 13

您对asyncLINQ的选择非常有限.正如另一个答案所指出的那样,您可以使用异步方法Select,但就是这样:

var tasks = FooSources.Select(source => source.GetFooAsync(fooId, cancellationToken));
Run Code Online (Sandbox Code Playgroud)

这将为您提供一系列的Task<Foo>.然后,您可以等待所有人完成:

var results = await Task.WhenAll(tasks);
Run Code Online (Sandbox Code Playgroud)

现在你有一个Foo可以过滤的数组:

return results.Where(foo => foo != null);
Run Code Online (Sandbox Code Playgroud)

请注意,这与原始代码的语义非常不同.await在开始下一个之前,您的原始代码将各自来源; 这个答案将开始所有来源,然后是await所有.

如果你想要foreach语义并且需要await在循环中,那么正确的解决方案是使用foreach包含一个循环await.没有直接的LINQ等价物.