繁体   English   中英

LINQ 中的 Where 子句调用异步方法

[英]Where clause in LINQ calling an async method

我在 class 中有一个方法定义为....

public static async Task<int> GetDCountAsync(int dId)

我试图在 LINQ Where 子句中调用此方法....

var excessD= dToConsider
    .Where(async x => await myService.GetDCountAsync(x.Id) >= x.Threshold)
    .Select(x => x.Id)
    .ToArray();

仅供参考:阈值是一个整数。

我收到异步错误....

'async' 匿名 function 的返回类型必须是 'void', 'Task', 'Task', ......

GetDCountAsync 的返回类型是异步任务。 我哪里错了? 提前致谢!

您可以使用System.Linq.Async package 中已有的功能:

int[] excessD = await dToConsider
    .ToAsyncEnumerable()
    .WhereAwait(async x => await myService.GetDCountAsync(x.Id) >= x.Threshold)
    .Select(x => x.Id)
    .ToArrayAsync();

WhereAwait算子的签名:

// Filters the elements of an async-enumerable sequence based on
// an asynchronous predicate.
public static IAsyncEnumerable<TSource> WhereAwait<TSource>(
    this IAsyncEnumerable<TSource> source,
    Func<TSource, ValueTask<bool>> predicate);

异步方法myService.GetDCountAsync将一次为一个元素调用和await ,而不是同时为所有元素调用和等待。

因此,您收到的完整错误消息将是:

无法将异步 lambda 表达式转换为委托类型“Func<int, bool>”。 异步 lambda 表达式可能会返回 void、Task 或 Task,它们都不能转换为“Func<int, bool>”。

它实际上告诉你的是 a.Where() LINQ 调用期望接受一个 int,并返回一个 boolean。但是因为你正在尝试进行异步调用,所以它试图返回 Task。

或者换句话说,编译器说“我看到你在这里使用异步方法,我知道异步方法只能返回 void、Task 或 Task,而且我也知道这个 Where 方法需要一个 bool 返回,所以我知道现在这是行不通的”

部分问题是我们实际上并不知道 dToConsider 是什么类型,在某些情况下,它会寻找延迟执行。 在任何情况下,因为您正在为 WHERE 语句执行自定义代码逻辑,所以我们假设这不是 EntityFramework 或需要延迟的东西,并说它只是一个列表。 在这种情况下,只需使用典型的 ForEach 循环来过滤您的列表即可。

var filteredItems = new List<T>();
foreach(var item in dToConsider)
{
    if(await myService.GetDCountAsync(x.Id) >= x.Threshold)
        filteredItems.Add(item);
}

我确定有人可能会使用 Task.WhenAll 等为您提供一个很好的扩展方法,但这是完成您需要完成的工作的最简单方法。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM