0

I was reading about the async pattern in C# in depth, and I decided to take Jon's advice and decompile the async code to actually see what was going on. And I came across two scenarios that confused me a bit as to why they were different.

Consider these two functions:

public static async Task<string> GetValue(){
    int count = 0;
    count++;
    string g = "asdf";
    var r = Task.FromResult<string> ("hello");
    return g;
}

And

public static async Task<string> GetValue(){
    int count = 0;
    count++;
    string g = "asdf";
    var r = await Task.FromResult<string> ("hello");
    return g;
}

Now I'd expect the code to ouput the same IL being that they are both async functions so there needs to be a state machine. But to my surprise the C# compiler does create the statemachine in both cases follows all the same code as one would expect, except in the first code block it doesn't actually save any information in the machine. Where in the second it does store all the variables.

Is there a reason that the compiler decides to not save the variables in the state machine and expose two different code paths based on the await keword?

0

3 Answers 3

2

The first one should have given you a warning about not really being async ("... will run synchronously") because there is no await in there.

So there is a state machine because you marked it async and it could be called with await.

But there is no information to keep because there is no await inside the method that would use it.

Sign up to request clarification or add additional context in comments.

9 Comments

It just seems kind of strange that even though there is no await and the statemachine is created it just decides not to keep track of anything, I'd like to know why the compiler goes through all the hassle doing all the async code and then just ignore storing anything. I understand why the statemachine exists for capturing exceptions and what not, but not sure why it would skip saving things at all. Are there performance impacts or something else I'm not seeing?
From the outside it still is (looks) async. Why wouldn't the compiler implement the state-machine? It has to handle an await call somehow.
Again that makes sense I'm just wondering why there is a specific case of if(!await keyword) don't push anything into the statemachine why even have that branch
@dbarnes Because the State Machine will hold the persistence for your async method with the await operator.
@dbarnes - There is no if(...) in your code, I don't get your last comment.
|
1

I believe the disparity stems from the lack of the await operator. Without the await the compiler is treating your code as synchronous code. Which has no reason to utilize the state machine.

So in essence it creates the state machine as it expects asynchronous code, but you do not actually implement any code that is async. Which keeps it as an empty container.

The setup code initializes the state machine used to represent the asynchronous method and then kicks it off using a call to the secondary MoveNext method on the state machine. This state machine type holds state for the asynchronous method, allowing that state to be persisted across asynchronous await points, if necessary.

The State Machine holds your data in your second example because of the await. This triggers the State Machine to persist the data through multiple await points. Since the other example doesn't contain await, it remains empty. It only created the State Machine because you decorated it as async though it really isn't.

A small excerpt from an article on the matter, hopefully this helps.

Comments

1

Only variable, that visible by await expression need to be captured:

public static async Task Method() {
    int a=3;
    Console.WriteLine(a);
    {
        int b=3;
        Console.WriteLine(b);
    }
    await Task.FromResult(true);
}

For example, in code above a captured, b not captured. So, if you does not use await, nothing need to be captured.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.