2017-02-09 7 views
0

По существу я пытаюсь быть в состоянии сделать это:Возможно ли вернуть список асинхронных элементов в асинхронном методе из источника async?

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

 Смежные вопросы

  • Нет связанных вопросов^_^