Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why does a bool "flag" get generated for the async/await state machine?

If you compile the following code:

private async Task<int> M()
{
    return await Task.FromResult(0);
}

And then decompile it (I used dotPeek) and examine the all-important MoveNext method, you will see a bool variable declared near the beginning; dotPeek chose "flag" for me.

bool flag = true;

In this case, you will see one subsequent consumer of that variable, in the default case statement after initiating the first async call:

if (!awaiter.IsCompleted)
{
    this.\u003C\u003E1__state = 0;
    this.\u003C\u003Eu__\u0024awaiter11 = awaiter;
    this.\u003C\u003Et__builder.AwaitUnsafeOnCompleted<TaskAwaiter<int>, Program.\u003CP\u003Ed__10>(ref awaiter, ref this);
    flag = false;
    return;
}

I've tried half a dozen more complicated examples than my initial one, and they are consistent in only assigning to this variable before exiting the method. So in other words, in all the cases I've tried so far, this variable is not only never consumed, but is only given a non-initial value immediately before returning from the method -- a point in time where the assignment is definitionally useless.

As background, I am enjoying the process of trying to implement async/await in Javascript via a C# -> JS cross-compiler. I'm trying to understand in what situation I need to consider the utility of this flag. At face, it seems spurious and therefore I should ignore it. However, I'd like to understand why the C# compiler introduces this variable -- I suspect there are more complicated expressions that consume this variable in a useful way.

To put is succinctly: Why does the C# compiler generate this flag variable?

like image 837
Kirk Woll Avatar asked Mar 13 '14 05:03

Kirk Woll


1 Answers

The following comment posted under the question describes its use:

Wrap your await statement in a try-finally block and set some variable inside the finally block. I don't fully understand what the IL logic is doing but I just did a quick look and it looks like it uses that flag variable to check when to execute code inside the finally block.

–Ilian Pinzon

Also Stephen Cleary adds some useful information for the interested reader. He recommends this blog series and in particular this blog post.

@IlianPinzon has the correct answer. This is explained in more detail in one of Jon Skeet's eduasync posts. Since you're writing a cross-compiler, I strongly recommend reading that whole series.

–Stephen Cleary

like image 179
2 revs, 2 users 71% Avatar answered Oct 01 '22 08:10

2 revs, 2 users 71%