基本上我试图做到这一点:
var thingTasks = thingFactory.GetMyThings();
// ...
var things = await thingTasks;
我试图从一个对象列表开始,遍历该列表,对每个对象进行async
调用,然后以await
方式返回结果集,这样就可以了消费者可以选择何时await
。 GetMyThings
本身在生成列表之前使用await
,因此它本身需要async
,如下所示:
public async Task<List<Thing>> GetMyThings() {
var thingMakers = await GetThingMakers();
var things = thingMakers.Select(async thing => await thing.GetAsync());
return things;
}
基本思路是我有一些await
行,然后我使用这些行的结果生成列表并生成每个项目也需要async
调用。我试图避免在方法中阻止(例如.Result
),而是将该责任/机会传递给调用者。基本上,在列表中启动任务,但不是await
。这自然让我想要返回Task<List<Thing>>
或&#39; List&gt;`。
我最接近的是return Task.WhenAll(things)
,但这不起作用(需要Task<Task<Thing[]>>
和await await GetMyThings()
。或者,return Select(...)
返回{{1}在消费方面需要Task<List<Task<Thing>>>
。
在这两种情况下,都需要双await Task.WhenAll(await GetMyThings())
语句来实现列表。我认为这是不可能的,但有没有办法避免双重await
?
答案 0 :(得分:1)
使用Task.WhenAll
一次等待所有任务。这样,您将大约同时运行每个GetAsync
。所以:
像这样:
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();
}
答案 1 :(得分:-1)
如果你想让内部任务在外面等待,你需要实际返回它们:
public async Task<List<Task<Thing>>> GetMyThings() {
var thingMakers = await GetThingMakers();
var things = thingMakers.Select(thing => thing.GetAsync());
return things.ToList();
}
然后您可以像这样使用此调用:
List<Task<Thing>> thingTasks = await GetMyThings();
await Task.WhenAll(thingTasks);
List<Thing> = thingTasks.Select(t => t.Result).ToList();
甚至:
List<Thing> things = await GetMyThings()
.ContinueWith(async r =>
{
await Task.WhenAll(r);
return r.Select(r => r.Result).ToList();
});