Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the purpose of IAsyncStateMachine.SetStateMachine?

Interface IAsyncStateMachine can be used only by compiler, and is used in generating state machine for async methods. Interface has SetMachineState - configures the state machine with a heap-allocated replica(from msdn).

I used ILSpy to decompile code and discover generated state machine and mentioned that implementation of SetMachineState function is always empty, like this

[CompilerGenerated]
private sealed class <GetResult>d__1 : IAsyncStateMachine
{
    //some fields to hold state

    void IAsyncStateMachine.MoveNext()
    { ... }

    [DebuggerHidden]
    void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
    {
        //Method is empty
    }
}

One more thing, generated state machine is a class not a struct as stated everywhere.

So, the question is: What the purpose of SetStateMachine function of IAsyncStateMachine interface, where is it used?

Original async function:

private static async Task<int> GetResult()
{
    var task = GetSomeData();
    DoSomeWork();
    return await task;
}
like image 264
Vasyl Senko Avatar asked Sep 13 '15 10:09

Vasyl Senko


1 Answers

This happens because you're looking at a debug build and not a release one.

Making the state-machine a struct is a compiler optimization. It enables not allocating memory when the awaitable is already completed when awaited. That optimization isn't necessary while debugging and it makes implementing debugging features in Visual Studio harder.

If you look at the same code compiled in release the state-machine will indeed be a struct and the SetStateMachine method will not be empty as this is the method that moves the state-machine from the stack to the heap:

[CompilerGenerated]
[StructLayout(LayoutKind.Auto)]
private struct <GetResult>d__1 : IAsyncStateMachine
{
    public AsyncTaskMethodBuilder<int> <>t__builder;
    ...

    [DebuggerHidden]
    void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
    {
        this.<>t__builder.SetStateMachine(stateMachine);
    }
}
like image 161
i3arnon Avatar answered Oct 17 '22 04:10

i3arnon