2017-02-09 40 views
0

基本上我想能夠做到這一點:是否有可能從異步源返回異步方法中的異步項列表?

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>>或'List>`。

我得到的最接近是return Task.WhenAll(things)但沒有工作(它需要的是Task<Task<Thing[]>>await await GetMyThings()。另外,return Select(...)返回Task<List<Task<Thing>>>並需要await Task.WhenAll(await GetMyThings())的消費方。

在這兩種情況下需要雙await語句來實現列表中。我想這是不可能的,但有沒有辦法避免雙重await

+2

'異步件事=>等待thing.GetAsync()'只是'事=> thing.GetAsync ()'也與'GetAsync'相同。不需要不必要地包裝它。 – Servy

+0

如果你不想讓調用者需要打開結果,那麼在返回結果之前,讓方法自己解開結果。該方法可以用與調用者一樣的方式解開結果。 – Servy

回答

1

使用Task.WhenAll在一次等待所有的任務。這樣,您將同時運行的每個GetAsync約時間。所以:

  1. 啓動所有任務
  2. 恭候所有
  3. 返回任務的結果

像這樣:

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

如果你想使內部任務等待着,能外,您需要實際歸還它們:

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