嵌套的Async/Await似乎没有伸缩
本文关键字:Async Await 嵌套 | 更新日期: 2023-09-27 17:53:20
我有以下(简化)代码:
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
操作都是"真正的异步"操作,这意味着它们都是I/o。
我使用Async/Await不正确的情况下?根据我目前的观察,它并没有达到我的预期。TPL数据流是我的解决方案吗?
对于GetData
的单个调用,嵌套的async/await调用不会引入任何并发性。您检索所有tierOne,然后检索tierOne-#1的所有tierTwo,然后检索tierTwo-#1的所有tierThrees,以此类推,所有这些都按顺序运行(尽管在GetTier*Async方法中可能存在一些并发性)。
如果你想并发请求,那么TPL Dataflow确实是一个更好的解决方案。