Asynchronous Code – Behind the Scenes – 003

Okay, I wasn’t quite realistic in the earlier post when I mentioned we would look at MoveNext in this one. I missed an important clog of the wheel. The SetStateMachine() method.

IAsyncStateMachine.SetStateMachine

We will only breifly visit the SetStateMachine method here, as the complete picture becomes more clear when we look to details of the MoveNext() method.

So how does the SetStateMachine method looks like in the generated code. Interestingly, it has two different implementation depending on whether you are in Release or Debug mode.

// Release Mode
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
    <>t__builder.SetStateMachine(stateMachine);
}

void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
    this.SetStateMachine(stateMachine);
}


// Debug Mode
[DebuggerHidden]
private void SetStateMachine(IAsyncStateMachine stateMachine)
{
}

void IAsyncStateMachine.SetStateMachine(IAsyncStateMachine stateMachine)
{
    this.SetStateMachine(stateMachine);
}

As one can observe, in the Debug Mode, the method is empty. Hence the following explanation is more relavant for the Release mode.

Let’s go back a bit and think about our little Stub method.

private static Task Bar()
{
	<Bar>d__2 stateMachine = new <Bar>d__2();
	stateMachine.<>t__builder = AsyncTaskMethodBuilder.Create();
	stateMachine.<>1__state = -1;
	stateMachine.<>t__builder.Start(ref stateMachine);
	return stateMachine.<>t__builder.Task;
}

When the State Machine is started by the Stub Method, it is residing on the Stack as a local variable of the Stub Method.

This is where the whole crazy stuff starts. When the State Machine pauses and resumes again, it needs a lot of information. For this to happen, when it pauses, the state machine has to box itself and store in heap, so that when it resumes, it has all the necessary informations. After it is boxed, the state machine is called on the box value using box value as arguement.

Do note that the boxing happens only once. The State machine also ensures that the builder has a reference to the single boxed version of the state machine.

This can be noticed if you dig a deep into the code of AsyncMethodBuilderCore.SetStateMachine

public void SetStateMachine(IAsyncStateMachine stateMachine)
{
	if (stateMachine == null)
	{
		throw new ArgumentNullException("stateMachine");
	}
	if (m_stateMachine != null)
	{
		throw new InvalidOperationException(Environment.GetResourceString("AsyncMethodBuilder_InstanceNotInitialized"));
	}
	m_stateMachine = stateMachine;
}

We will leave the SetStateMachine here because that’s all it does. Its role would be more visible once we examine the MoveNext method in detail.

One thought on “Asynchronous Code – Behind the Scenes – 003

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s