19

尝试await在查询中使用关键字LINQ,我得到了这个:

'await' 运算符只能用于初始 'from' 子句的第一个集合表达式中的查询表达式或 'join' 子句的集合表达式中

示例代码:

var data = (from id in ids
            let d = await LoadDataAsync(id)
            select d);

是否不可能在LINQ查询中等待某些内容,或者是否需要以不同的方式构造?

4

3 回答 3

26

LINQ 对async/的支持非常有限await。对于 LINQ-to-objects,我所知道的唯一真正有用的操作是Select使用async委托(这会导致一系列任务)。

List<T> data = new List<T>();
foreach (var id in ids)
  data.Add(await LoadDataAsync(id));

如果您可以LoadDataAsync安全地并行执行,您的示例可以重写为:

T[] data = await Task.WhenAll(ids.Select(id => LoadDataAsync(id)));
于 2013-05-18T13:34:22.190 回答
3

您可以自己定义一些异步 linq 操作(用于 linq to objects):例如:您可以编写自己的 WhereAsync 扩展方法:

public static async Task<IEnumerable<T>> WhereAsync<T>(
this IEnumerable<T> target, Func<T, Task<bool>> predicateAsync)
{
   var tasks = target.Select(async x => new { Predicate = await predicateAsync(x).ConfigureAwait(false), Value = x }).ToArray();
   var results = await Task.WhenAll(tasks).ConfigureAwait(false);

   return results.Where(x => x.Predicate).Select(x => x.Value);
}

并像这样使用它:

var ints = new List<int> { 1, 2, 3 };
var smallInts = await ints.WhereAsync(IsSmallIntAsync);
于 2015-01-29T12:38:51.633 回答
0

使用响应式扩展,可以像这样异步处理 linq 查询的结果:

(from d in ids
select LoadDataAsync(d).ToObservable()).Merge()

这为您提供了一个可观察的流,您可以以各种方式响应。例如,您可以将结果缓冲到一个带有超时的列表中。

上面实质上是说“对于 ids 中的每个 d,对其应用一个异步函数,该函数为每个 d 产生一个任务,并将其视为单个结果的 observable (ToObservable),并将所有这些 observable 一起视为单个可观察流(合并)

于 2018-01-23T16:18:36.123 回答