C# Async/Await Under the Hood
Many of us use the async await operation in C# frequently, but how often do you peek under the hood? There’s a secret sauce that a lot of developers are unaware of that occurs. We’re going to take into the inner workings and find out where those extra clock-cycles go. The extra knowledge may help you write more efficient code.
Sample Code
Console.WriteLine("Hello");
await Task.Yield();
Console.WriteLine("World");
Generated IL
IL_000a: ldstr "Hello" IL_000f: call void [System.Console]System.Console::WriteLine(string) IL_0014: call valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable [System.Runtime]System.Threading.Tasks.Task::Yield() IL_0019: stloc.2 IL_001a: ldloca.s V_2 IL_001c: call instance valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable::GetAwaiter() IL_0021: stloc.1 IL_0022: ldloca.s V_1 IL_0024: call instance bool [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter::get_IsCompleted() IL_0029: brtrue.s IL_0067 IL_002b: ldarg.0 IL_002c: ldc.i4.0 IL_002d: dup IL_002e: stloc.0 IL_002f: stfld int32 Program/'<<Main>$>d__0'::'<>1__state' IL_0034: ldarg.0 IL_0035: ldloc.1 IL_0036: stfld valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter Program/'<<Main>$>d__0'::'<>u__1' IL_003b: ldarg.0 IL_003c: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder Program/'<<Main>$>d__0'::'<>t__builder' IL_0041: ldloca.s V_1 IL_0043: ldarg.0 IL_0044: call instance void [System.Runtime]System.Runtime.CompilerServices.AsyncTaskMethodBuilder::AwaitUnsafeOnCompleted<valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter, valuetype Program/'<<Main>$>d__0'>(!!0&, !!1&) IL_0049: leave.s IL_00a4 IL_004b: ldarg.0 IL_004c: ldfld valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter Program/'<<Main>$>d__0'::'<>u__1' IL_0051: stloc.1 IL_0052: ldarg.0 IL_0053: ldflda valuetype [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter Program/'<<Main>$>d__0'::'<>u__1' IL_0058: initobj [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter IL_005e: ldarg.0 IL_005f: ldc.i4.m1 IL_0060: dup IL_0061: stloc.0 IL_0062: stfld int32 Program/'<<Main>$>d__0'::'<>1__state' IL_0067: ldloca.s V_1 IL_0069: call instance void [System.Runtime]System.Runtime.CompilerServices.YieldAwaitable/YieldAwaiter::GetResult() IL_006e: ldstr "World" IL_0073: call void [System.Console]System.Console::WriteLine(string) IL_0078: leave.s IL_0091 IL_007a: stloc.3