Nested Async/Await не выглядит масштабируемым

У меня есть следующий (упрощенный) код:

public async Task GetData(DomainObject domainObject, int depth)
{
  // This async operation is really quick, and there's usually like five.
  IEnumerable<TierOne> tierOnes = await domainObject.GetTierOnesAsync();

  var tierOneTasks = tierOnes.Select(async tierOne => 
  {
    // This async operation is really quick and there's usually like three.
    IEnumerable<TierTwo> tierTwos = await tierOne.GetTierTwosAsync();

    if (depth <= TierTwoDepth)
      return;

    var tierTwoTasks = tierTwos.Select(async tierTwo => 
    {
      // This async operation is usually fast, and there's usually >= 100.
      IEnumerable<TierThree> tierThrees = await tierTwo.GetTierThreesAsync();

      if (depth <= TierThreeDepth)
        return;

      var tierThreeTasks = tierThrees.Select(async tierThree => 
      {
        // This async operation is SLOW, and there's usually.. 50?
        await tierThree.GetTierFoursAsync();
      });

      await Task.WhenAll(tierThreeTasks.ToArray());
    });

    await Task.WhenAll(tierTwoTasks.ToArray());
  });

  await Task.WhenAll(tierOneTasks.ToArray());
}

Судя по тому, что я видел, это не очень хорошо масштабируется. Все Async Операции являются "истинно асинхронными" операциями, означающими, что все они являются вводом / выводом

Я неправильно использую Async / Await для этого сценария? Исходя из моих текущих наблюдений, он не соответствует ожиданиям. Будет ли TPL DataFlow моим решением?

1 ответ

Для одного звонка GetDataВложенные асинхронные / ожидающие вызовы не создают параллелизма. Вы извлекаете все tierOnes, затем все tierTwos для tierOne-#1, затем все tierThrees для tierTwo-#1 и т. Д., Все выполняются последовательно (хотя в методах GetTier*Async может быть некоторый параллелизм).

Если вам нужны параллельные запросы, тогда TPL Dataflow - действительно лучшее решение.

Другие вопросы по тегам