| "An await expression does not block the thread on which it is executing. Instead, it causes the compiler to sign up the rest of the async method as a continuation on the awaited task. Control then returns to the caller of the async method. When the task completes, it invokes its continuation, and execution of the async method resumes where it left off."
The implementation detail is that your caller's state needs to somehow be re-asserted when the asynchronous wait finishes evaluating- anyone mildly versed in computer hardware knows that to, in most situations (some green threading environments aside) be a very onerous scary intensive thing, speak nothing of the tasks of capturing and storing the continuation, which likely is fairly deep in a call stack somewhere.
It's great magic, it's certainly putting a lot of magic programmers like to use at their fingertips. But be advised that it is somewhat scary, handing out magic wands like candy to newcomers and telling them it's OK and good.
It's sorta unfortunate magic because it's a special case in the compiler. Instead of having a general use monad-like syntax, "await" gets special treatment. Compare this to F#'s approach, where the equivalent feature (async in F#) is just a library.
The actual transformations should be quite straight forward and give you the "pyramid" code the article mentions.
The magic that will bite you isn't the transformation as much as the runtime library that handles threading and the hidden choices made for you there. For instance, in ASP.NET, doing fooAsync().Result causes a deadock.
It's only magic if it's poorly or non-documented. I'm aware of many of the internals, and have written my own SynchronizationContext before. Execution actually can (and often) does continue using the same thread.
I still strongly believe it's better to make cool things available rather than try and protect people from themselves.
I'd fallen out of the .NET world before Async/Await arrived, but were someone to put some under-the-hood-monkeying around-with-it docs under my nose, I'd love to brush up. I seem to have osmosed that there is some compiler transforming going on, but I've not been exposed to ways to monkey around, did not know there was more than a use-only black box: would be lovely to get an engine-bay tour. Have you any recommendations?
For what it's worth, this is exactly how Parse's .NET SDK works. Promises in JavaScript go a long way toward improving the experience of async development, but I thoroughly agree that language-level support for this type of construct is immensely helpful.