如何在返回集合的 lambda 中使用异步

Posted

技术标签:

【中文标题】如何在返回集合的 lambda 中使用异步【英文标题】:How to use async within a lambda which returns a collection 【发布时间】:2015-07-01 12:14:09 【问题描述】:

我有一个异步“上游”方法。我正在尝试遵循最佳实践,并在堆栈中全力以赴。

在 MVC 中的控制器操作中,如果我依赖 .Result(),我可以预见会遇到死锁问题。

将控制器操作更改为异步似乎是可行的方法,但问题是异步方法在 lambda 中被多次调用。

如何等待返回多个结果的 lamda

public async Task<JsonResult>  GetLotsOfStuff()

    IEnumerable<ThingDetail> things=  previouslyInitialisedCollection
                                      .Select(async q => await GetDetailAboutTheThing(q.Id)));
    return Json(result, JsonRequestBehavior.AllowGet);


你可以看到我已经尝试使 lambda 异步,但这只是给出了一个编译器异常:

无法转换源类型

System.Collections.Generic.IEnumerable&lt;System.Threading.Tasks.Task&lt;ThingDetail&gt; 到目标类型System.Collections.Generic.IEnumerable&lt;ThingDetail&gt;

我哪里错了?

【问题讨论】:

现在您选择返回带有任务的枚举,但是您尝试将其分配给带有 ThingDetail 的枚举,因为您可以使用 var 关键字直接声明类型,例如:var things=... 而不是 IEnumerable&lt;ThingDetail&gt; things = ... result 未在代码块中定义。大概,你的意思是return Json(things, JsonRequestBehavior.AllowGet) 【参考方案1】: 将您的Things 集合转换为Task&lt;Thing&gt;s 的集合。 然后使用Task.WhenAll 加入所有这些任务并等待它。 等待联合任务会给你一个Thing[]

public async Task<JsonResult>  GetLotsOfStuff()

    IEnumerable<Task<ThingDetail>> tasks = collection.Select(q => GetDetailAboutTheThing(q.Id));

    Task<int[]> jointTask = Task.WhenAll(tasks);

    IEnumerable<ThingDetail> things = await jointTask;

    return Json(things, JsonRequestBehavior.AllowGet);

或者,简洁地使用类型推断:

public async Task<JsonResult>  GetLotsOfStuff()

    var tasks = collection.Select(q => GetDetailAboutTheThing(q.Id));
    var things = await Task.WhenAll(tasks);

    return Json(things, JsonRequestBehavior.AllowGet);

小提琴:https://dotnetfiddle.net/78ApTI

注意:由于GetDetailAboutTheThing 似乎返回Task&lt;Thing&gt;,因此约定是将Async 附加到其名称 - GetDetailAboutTheThingAsync

【讨论】:

“就是这样”。太好了,谢谢。我曾尝试过WhenAll 方法,但显然错过了一个中间步骤。我同意你关于异步方法命名约定的观点,我同意。我会实现这个。 两个代码块的最后一行不应该是return Json(things, JsonRequestBehavior.AllowGet);吗? result 似乎没有在两个代码块中定义。 @M.Babcock 正确,现在已修复。谢谢

以上是关于如何在返回集合的 lambda 中使用异步的主要内容,如果未能解决你的问题,请参考以下文章

如何在 SelectMany 中使用异步 lambda?

如何使用无服务器框架从另一个 lambda 异步调用 lambda

如何在 AWS Lambda 中等待异步操作?

如何使用 lambda 在对象中打印集合列表

如何让 Lambda 函数等待异步操作完成?

如何从 lambda 函数异步传递红移查询?