6

我有这个简单的循环,我想使用 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;
    }

我希望看起来像:

return FooSources.Where(...).FirstOrDefault();

我被困住了,尤其是在使 LINQ 和async/await一起工作方面。

4

1 回答 1

13

您对asyncLINQ 的选择非常有限。正如另一个答案指出的那样,您可以在 中使用异步方法Select,仅此而已:

var tasks = FooSources.Select(source => source.GetFooAsync(fooId, cancellationToken));

这将为您提供一系列Task<Foo>. 然后,您可以等待它们全部完成:

var results = await Task.WhenAll(tasks);

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

return results.Where(foo => foo != null);

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

如果您想要foreach语义并且需要await在循环内部,那么正确的解决方案是使用foreach包含await. 没有直接的 LINQ 等效项。

于 2013-05-31T22:03:35.350 回答