如何使用LINQ Select调用异步lambda表达式?

3
考虑以下代码...
List<myobject> items = dbItems.Select(x => ConvertDatabaseItem(x)).ToList();

private async Task<myobject> ConvertDatabaseItem(DataObjects.mydbobject x)
{
    var item = x.ToContract();
    await SetOtherInfo(item);
    return item;
}

这段代码无法编译,因为我们需要等待 ConvertDatabaseItem 方法完成...

List<myobject> items = dbItems.Select(async x => await ConvertDatabaseItem(x)).ToList();

然而,这样做是行不通的,因为我们仍然需要等待异步lambda表达式,否则将会导致编译错误(List< Task< myobject >> 转换为 List< myobject >)。

List<myobject> items = dbItems.Select(await (async x => await ConvertDatabaseItem(x))).ToList();

然而这会出现一个“无法等待lambda表达式”的错误。我是否遗漏了什么愚蠢的内容或者这个操作不可能实现?

你想如何处理这些任务?一个接一个地创建并等待它们,还是先全部创建然后并发地等待它们? - Theodor Zoulias
2个回答

4

尝试使用Task.WhenAll方法。你的解决方案应该是这样的:

var items = await Task.WhenAll(dbItems.Select(ConvertDatabaseItem));

这是针对此特定情况的最佳解决方案。请注意,它将返回一个数组(myobject[]),而不是 List<myobject> - Gabriel Luci
@GabrielLuci 是的,该方法返回 Task<TResult[]>。应该牢记这个特性。通常情况下最好使用 IEnumerable<TResult>IReadOnlyCollection<TResult> 或其他接口来工作,以便调用者不依赖于特定的实现。 - Didgeridoo

0

谢谢Didgeridoo...我最终进行了以下调用...

List<myobject> items = (await Task.WhenAll(dbItems.Select(async x =>
{
    var item = x.ToContract();
    await SetOtherInfo(..., item);
    return item;
}))).ToList();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接