是否可以从异步源返回异步方法中的异步项列表?

时间:2017-02-09 22:33:26

标签: c# async-await

基本上我试图做到这一点:

var thingTasks = thingFactory.GetMyThings();
// ...
var things = await thingTasks;

我试图从一个对象列表开始,遍历该列表,对每个对象进行async调用,然后以await方式返回结果集,这样就可以了消费者可以选择何时awaitGetMyThings本身在生成列表之前使用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

2 个答案:

答案 0 :(得分:1)

使用Task.WhenAll一次等待所有任务。这样,您将大约同时运行每个GetAsync。所以:

  1. 开始所有任务
  2. 等待所有
  3. 返回任务的结果
  4. 像这样:

    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();
        });