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 - действительно лучшее решение.