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

时间:2020-11-26 19:33:16

I have a method which is Async "upstream". I'm trying to follow best practice and go all-in qith async all the way up the stack.

我有一个异步“上游”的方法。我正在尝试遵循最佳实践并在堆栈中一直进行qith异步。

Within a Controller action within MVC I predictably hit the deadlock issue If I rely on .Result().

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

Changing the Controller action to async seems to be the way to go, though the issue is that the async method is called multiple times within a lambda.

将Controller操作更改为异步似乎是要走的路,尽管问题是在lambda中多次调用async方法。

How can I await on a lamda that returns multiple results?

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

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

}

You can see I have tried making the lambda async, but this just gives a compiler exception:

您可以看到我尝试使lambda异步,但这只是一个编译器异常:

Cannot convert source type

无法转换源类型

System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<ThingDetail> to target type System.Collections.Generic.IEnumerable<ThingDetail>

System.Collections.Generic.IEnumerable 到目标类型System.Collections.Generic.IEnumerable

Where am I going wrong here?

我在哪里错了?

1 个解决方案

#1


15  

  • Convert your collection of Things into a collection of Task<Thing>s.
  • 将您的Things集合转换为Task 的集合。
  • Then join all those tasks using Task.WhenAll and await it.
  • 然后使用Task.WhenAll加入所有这些任务并等待它。
  • Awaiting the joint task will give you a 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);
}

Or, succinctly and using type inference:

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

public async Task<JsonResult>  GetLotsOfStuff()
{
    var tasks = collection.Select(q => GetDetailAboutTheThing(q.Id));
    var things = await Task.WhenAll(tasks);

    return Json(things, JsonRequestBehavior.AllowGet);
}

Fiddle: https://dotnetfiddle.net/78ApTI

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

Note: since GetDetailAboutTheThing seems to return a Task<Thing>, the convention is to append Async to its name - GetDetailAboutTheThingAsync.

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

#1


15  

  • Convert your collection of Things into a collection of Task<Thing>s.
  • 将您的Things集合转换为Task 的集合。
  • Then join all those tasks using Task.WhenAll and await it.
  • 然后使用Task.WhenAll加入所有这些任务并等待它。
  • Awaiting the joint task will give you a 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);
}

Or, succinctly and using type inference:

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

public async Task<JsonResult>  GetLotsOfStuff()
{
    var tasks = collection.Select(q => GetDetailAboutTheThing(q.Id));
    var things = await Task.WhenAll(tasks);

    return Json(things, JsonRequestBehavior.AllowGet);
}

Fiddle: https://dotnetfiddle.net/78ApTI

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

Note: since GetDetailAboutTheThing seems to return a Task<Thing>, the convention is to append Async to its name - GetDetailAboutTheThingAsync.

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