【问题标题】:Convert async loop to LINQ query将异步循环转换为 LINQ 查询
【发布时间】:2013-06-01 06:03:35
【问题描述】:

我想使用 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 一起工作。

【问题讨论】:

  • 你也可以在 lambda 中使用异步 :)
  • 安装 resharper,您可以将此类循环转换为 lambda 表达式
  • @FabianBigler:在答案中向我们展示那会是什么样子。

标签: c# linq async-await


【解决方案1】:

async LINQ 的选项非常有限。正如另一个答案所指出的,您可以在Select 中使用异步方法,但仅此而已:

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

这将为您提供Task&lt;Foo&gt; 的序列。然后,您可以等待它们全部完成:

var results = await Task.WhenAll(tasks);

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

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

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

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-08-08
    • 2014-08-14
    相关资源
    最近更新 更多