长异步等待链会导致大量内存消耗吗?(理论上)

查看这段代码:


public async Task<T> ConsumeAsync()

    {

          await a();

          await b();

          await c();

          await d();

          //..

    }

假设a,b,c,d还有嵌套的异步等待(等等)


异步/等待 POV - 对于每个await,都有一个状态机被保留。


问题(理论):


由于每个状态机都保存在内存中,这是否会导致内存消耗大?

这可能是一个模糊的问题,但如果有很多状态,似乎不可避免地不会怀疑所保留的状态机的大小。


人到中年有点甜
浏览 88回答 3
3回答

慕沐林林

由于每个状态机都保存在内存中,这会不会导致内存消耗大?不太可能。每个状态机将在外部占用几十个字节。所以只有当你有很多的时候才重要。嵌套并不会真正导致这种情况,而是执行Task[]可能的成员。但这并不是任何其他资源类型的新内容或不同之处。

GCT1015

异步/等待 POV - 对于每个 await ,都有一个状态机被保留。不对。编译器为每个async方法生成一个状态机。方法中的局部变量被提升到状态机上的字段中。方法的主体(基本上)被分解为一个switch语句,每个语句case对应于await语句之间的方法的一部分。Anint用于跟踪方法的哪一部分已被执行(即case接下来应该执行哪一部分)。您的方法a()、b()等可能有自己的状态机,也可能没有(取决于它们是否被标记async)。即使他们这样做,在您的示例中,一次也只会实例化其中一个状态机。SharpLab 是探索这些内容的绝佳资源。例子。

子衿沉夜

有一个额外的成本,但它是相对苗条的。与常规功能相比的额外费用:状态机类这个类的实例一个 int 用于执行阶段AsyncTaskMethodBuilder 实例此外,函数的局部变量将被转换为状态机的字段。这会将一些内存从堆栈移动到堆。我建议反编译一些简单的异步函数,以查看生成的状态机并有一个直觉会发生什么。也有一些在线工具可以做到这一点(比如 sharplab.io)查看一个简单的异步函数的反编译结果
打开App,查看更多内容
随时随地看视频慕课网APP