[英]Is it possible to return a list of async items in an async method from an async source?
Essentially I'm trying to be able to do this: 本质上,我试图做到这一点:
var thingTasks = thingFactory.GetMyThings();
// ...
var things = await thingTasks;
I'm trying to start from a list of objects, iterate through that list making an async
call for each one, and returning the set of results in an await
-able way so the consumer can choose when to await
it. 我试图从对象列表开始,遍历该列表,对每个对象进行async
调用,并以一种可await
方式返回结果集,以便消费者可以选择何时await
它。 GetMyThings
itself uses await
before generating the list, so it needs to be async
itself and is something like: GetMyThings
本身在生成列表之前会使用await
,因此它本身必须是async
,类似于:
public async Task<List<Thing>> GetMyThings() {
var thingMakers = await GetThingMakers();
var things = thingMakers.Select(async thing => await thing.GetAsync());
return things;
}
The basic idea is that I have some await
lines, then after that I use the results of those lines to generate a list and generating each item also requires an async
call. 基本思想是,我有一些await
行,然后使用这些行的结果来生成列表,并且生成每个项目还需要async
调用。 I'm trying to avoid blocking within the method (eg .Result
) and instead pass that responsibility/opportunity back to the caller. 我试图避免在方法内阻塞(例如.Result
),而是将这种责任/机会传递回调用者。 Basically, start the tasks in the list but not await
them. 基本上,启动列表中的任务,但不await
它们。 This naturally makes me want to return Task<List<Thing>>
or 'List>`. 这自然使我想返回Task<List<Thing>>
或'List>`。
The closest I got was return Task.WhenAll(things)
but that didn't work (it needed to be Task<Task<Thing[]>>
and await await GetMyThings()
. Alternatively, return Select(...)
returning a Task<List<Task<Thing>>>
and needing a await Task.WhenAll(await GetMyThings())
on the consuming side. 我最接近的是return Task.WhenAll(things)
但是没有用(必须是Task<Task<Thing[]>>
并await await GetMyThings()
。或者, return Select(...)
返回a Task<List<Task<Thing>>>
并且需要await Task.WhenAll(await GetMyThings())
在使用方。
In both cases one needs double await
statements to realize the list. 在这两种情况下,都需要双重await
语句来实现该列表。 I'm thinking it's impossible but is there a way to avoid the double await
? 我认为这是不可能的,但是有没有办法避免双重await
呢?
Use Task.WhenAll
to await all task at once. 使用Task.WhenAll
一次等待所有任务。 This way you will run each GetAsync
approximately at the same time. 这样,您将大约同时运行每个GetAsync
。 So : 因此:
Like this : 像这样 :
public async Task<List<Thing>> GetMyThings()
{
var thingMakers = await GetThingMakers();
var tasks = thingMakers.Select(thing => thing.GetAsync());
var things = await Task.WhenAll(tasks);
return things.ToList();
}
If you want to make the inner tasks await-able outside, you need to actually return them: 如果要使内部任务可以在外部等待,则需要实际返回它们:
public async Task<List<Task<Thing>>> GetMyThings() {
var thingMakers = await GetThingMakers();
var things = thingMakers.Select(thing => thing.GetAsync());
return things.ToList();
}
You can then use this call like this: 然后,您可以像下面这样使用此调用:
List<Task<Thing>> thingTasks = await GetMyThings();
await Task.WhenAll(thingTasks);
List<Thing> = thingTasks.Select(t => t.Result).ToList();
Or even: 甚至:
List<Thing> things = await GetMyThings()
.ContinueWith(async r =>
{
await Task.WhenAll(r);
return r.Select(r => r.Result).ToList();
});
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.