Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does compiler perform "return value optimization" on chains of async methods

Not return value optimization in the traditional sense, but I was wondering when you have a situation like this:

private async Task Method1()
{
    await Method2();
}

private async Task Method2()
{
    await Method3();
}

private async Task Method3()
{
    //do something async
}

This could obviously be written more optimally:

private Task Method1()
{
    return Method2();
}

private Task Method2()
{
    return Method3();
}

private async Task Method3()
{
    //do something async
}

I just wondered whether anyone knew if the (MS) compiler was clever enough not to generate state machines for Method1() and Method2() in the first instance?

like image 296
GazTheDestroyer Avatar asked Mar 21 '14 09:03

GazTheDestroyer


1 Answers

No, the C# compiler doesn't optimize it and it should not. These are conceptually two different things, here is a similar question.

IMO, the major difference is in how exceptions are getting propogated into the caller of Method1 and Method2. I demo'ed this behavoir here.

In the first case (without the state machine), an exception will be immediately thrown on the caller's stack frame. If it is unhanded, the app may crash right away (unless there is another async method in the chain of calls on the same stack frame).

In the second case (with the state machine), an exception will remain dormant in the Task object returned to the caller, until it is observed via await task or task.Wait(), some time later. It may get observed on a completely different stack frame, or may not get observed at all. I posted some more details about this here.

like image 53
noseratio Avatar answered Oct 21 '22 03:10

noseratio