In my Async Programming in .Net talk I like to show what’s really happening under the covers with the new async/await keywords in VS 2012. To show this, I’m currently using ILSpy instead of Reflector because it is free. I noticed an “issue” tonight when trying to locate the MoveNext method of the state machine generated class, but couldn’t find it. To begin, let’s look at the code sample.
Module AsyncWorld Sub DoWorkAsync() PrintIt() Console.ReadLine() End Sub Public Async Sub PrintIt() Dim text = "Hello World" Await Task.Factory.StartNew( Sub() Threading.Thread.Sleep(2000) Console.WriteLine(text) End Sub) Console.WriteLine("Done") End Sub End Module
Ignoring the potential code smell of an Async Sub (async void in C#), let’s take a look at what IL Spy gives us out of the box for the generated classes:
Here we can see that the generated closure is displayed with the contained Lambda, but the underlying state machine that manages the closure is missing. If you want to see the state machine, click on Tools – Options and uncheck the “Decompile async methods (async/await)” option.
Once you deselect that, refresh your project to see the compiler generated state machine:
My, that’s a lot of code for our simple Console Writeline task. Can’t find it? It’s called in the line
taskAwaiter = Task.Factory.StartNew(New Action(Me.$VB$ResumableLocal_$VB$Closure_ClosureVariable_1$1._Lambda$__1)).GetAwaiter().
Remember the closure we saw above? Our code’s still in there. The state machine just lets us call this asynchronously trapping for exceptions as necessary. In most cases, you don’t need to worry about all of this compiler generated code. You should be aware of it though if you are writing code with lots of awaits in a single method, particularly in tight loops. Your performance will suffer in those cases. It is better to work more natively with the TPL Task objects with continuations than using await/async in those cases. For more information, I highly recommend that you check out Steven Toub’s Zen of Async session from Build 2011.
If you want to try this out more, download my async samples including comparative examples using Callbacks, APM, Tasks, Async/Await, and Reactive Extensions (Rx).