C# Async/Await Under the Hood

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