In October 2011, as we were developing async, I prepared this super low-level talk so that my colleagues on the compiler and CLR/JIT teams would understand what code the compiler generates for async methods. It's deep, and technical, and not of practical use to most people who just use async. But if you're already an async expert then you might find some useful nuggets of information:
I gave this talk internally at Microsoft on 2011.10.11:
Brain-teaser: Here's a puzzle for you. After an await, the compiler calls "awaiter.GetResult()", and then nulls out the awaiter field (to allow it to be garbage-collected), and then resets the state field back to -1. Why does it bother resetting the state? Or more precisely, can you come up with an example async method where, if the state weren't reset, then it would have wrong behavior?
Hint: you'll need a try and a loop. (I whited out the text: you'll have to select it to read the hint)
Answer: Jon Skeet figured it out! ... here on stackoverflow.