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.
Within a Controller action within MVC I predictably hit the deadlock issue If I rely on .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.
How can I await on a lamda that returns multiple results?
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:
Cannot convert source type
System.Collections.Generic.IEnumerable<System.Threading.Tasks.Task<ThingDetail>
to target typeSystem.Collections.Generic.IEnumerable<ThingDetail>
Where am I going wrong here?
Async methods can have the following return types: Task, for an async method that performs an operation but returns no value. Task<TResult>, for an async method that returns a value. void , for an event handler.
Async Method Return Types There are three return types that a method marked async may have: void. Task. Task< T > for some type T.
Async functions always return a promise. If the return value of an async function is not explicitly a promise, it will be implicitly wrapped in a promise.
Thing
s into a collection of Task<Thing>
s.Task.WhenAll
and await it.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
Note: since GetDetailAboutTheThing
seems to return a Task<Thing>
, the convention is to append Async
to its name - GetDetailAboutTheThingAsync
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With