Async recursion. Where is my memory actually going?

后端 未结 2 1053
伪装坚强ぢ
伪装坚强ぢ 2021-01-12 08:12

This is asked more out of curiosity than with regards to any real-world problem.

Consider the following code:

void Main()
{
    FAsync().Wait();
}

         


        
2条回答
  •  陌清茗
    陌清茗 (楼主)
    2021-01-12 08:36

    The compiler turns your async method into a state machine struct. The struct is created firstly on the stack. When you await an uncompleted task (otherwise it continues running synchronously and will cause an overflow of the stack) that state machine is boxed and moved to the heap.

    For example this method:

    public async Task M()
    {
    }
    

    is turned into this state machine:

    private struct d__0 : IAsyncStateMachine
    {
        public int <>1__state;
        public AsyncTaskMethodBuilder <>t__builder;
        void IAsyncStateMachine.MoveNext()
        {
            try
            {
            }
            catch (Exception exception)
            {
                this.<>1__state = -2;
                this.<>t__builder.SetException(exception);
                return;
            }
            this.<>1__state = -2;
            this.<>t__builder.SetResult();
        }
        [DebuggerHidden]
        void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
        {
            this.<>t__builder.SetStateMachine(stateMachine);
        }
    }
    

    So, in "traditional" recursion the state for each iteration is stored on the stack so too many iterations can overflow that memory. In an async method the state is stored on the heap and it may overflow as well (though it's usually much bigger).

提交回复
热议问题