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

Roy*_*mir 5 .net c# async-await

看这段代码:

public async Task<T> ConsumeAsync()
    {
          await a();
          await b();
          await c();
          await d();
          //..
    }
Run Code Online (Sandbox Code Playgroud)

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

异步/等待POV-每个await,都保留着一个状态机。

问题(理论上):

由于每个状态机都保留在内存中,这会导致大量内存消耗吗?
提出这个问题可能是一个模糊的问题,但是如果有很多状态,似乎不可避免地要问是否保留了状态机的大小。

Hen*_*man 8

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

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

因此,只有当您有很多时,它才重要。嵌套并不会真正导致这种情况,而是执行强大的成员Task[]

但这并不是真正的新事物,也不是与其他任何资源类型不同的形式。


can*_*on7 6

异步/等待POV-每次等待,都会保留一个状态机。

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

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

SharpLab是探索此类材料的绝佳资源。实例

  • @TheodorZoulias请提供有关该主张的一些证据。状态机是一个结构,将其装箱在* first *等待中[此处](https://referencesource.microsoft.com/#mscorlib/system/runtime/compilerservices/AsyncMethodBuilder.cs,546),然后该框是缓存以备后用。 (2认同)
  • 1)每个`async`方法都获得一个状态机; 2)每次调用该方法时都会实例化该状态机; 3)不同的方法具有不同的状态机。一个async方法的状态机为* entire *方法服务。没有一种方法可以有多个状态机。 (2认同)