为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
人到中年有点甜 2022-12-24 10:37:29
查看这段代码:public async Task<T> ConsumeAsync()    {          await a();          await b();          await c();          await d();          //..    }假设a,b,c,d还有嵌套的异步等待(等等)异步/等待 POV - 对于每个await,都有一个状态机被保留。问题(理论):由于每个状态机都保存在内存中,这是否会导致内存消耗大?这可能是一个模糊的问题,但如果有很多状态,似乎不可避免地不会怀疑所保留的状态机的大小。
查看完整描述

3 回答

?
慕沐林林

TA贡献2016条经验 获得超9个赞

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

不太可能。每个状态机将在外部占用几十个字节。

所以只有当你有很多的时候才重要。嵌套并不会真正导致这种情况,而是执行Task[]可能的成员。

但这并不是任何其他资源类型的新内容或不同之处。


查看完整回答
反对 回复 2022-12-24
?
GCT1015

TA贡献1827条经验 获得超4个赞

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

不对。编译器为每个async方法生成一个状态机。方法中的局部变量被提升到状态机上的字段中。方法的主体(基本上)被分解为一个switch语句,每个语句case对应于await语句之间的方法的一部分。Anint用于跟踪方法的哪一部分已被执行(即case接下来应该执行哪一部分)。

您的方法a()b()等可能有自己的状态机,也可能没有(取决于它们是否被标记async)。即使他们这样做,在您的示例中,一次也只会实例化其中一个状态机。

SharpLab 是探索这些内容的绝佳资源。例子


查看完整回答
反对 回复 2022-12-24
?
子衿沉夜

TA贡献1828条经验 获得超3个赞

有一个额外的成本,但它是相对苗条的。

与常规功能相比的额外费用:

  • 状态机类

  • 这个类的实例

  • 一个 int 用于执行阶段

  • AsyncTaskMethodBuilder 实例

此外,函数的局部变量将被转换为状态机的字段。这会将一些内存从堆栈移动到堆。

我建议反编译一些简单的异步函数,以查看生成的状态机并有一个直觉会发生什么。

也有一些在线工具可以做到这一点(比如 sharplab.io)查看一个简单的异步函数的反编译结果


查看完整回答
反对 回复 2022-12-24
  • 3 回答
  • 0 关注
  • 87 浏览

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号