Why did Microsoft implement the new task-based async pattern differently for Desktop apps and Metro-style apps?
Saturday, August 11, 2012 10:29 AM
I do understand the way a method marked with async is compiled into a state machine in IL code for Desktop applications (see for example the Aync/Await FAQ). The basic part is that await waits for an "awaitable" that returns an "awaiter" via it's GetAwaiter method. The idea behind this is obviously that await can await anything, not just methods that return tasks.
But for WinRT await does not wait for an awaitable or use an awaiter. Instead the code apparently (I did not check that so far) invokes the Completed delegate that is part of all four interfaces that an async WinRT method can return (IAsyncAction, IAsyncActionWithProgress<TProgress>, IAsyncOperation<TResult>, IAsyncOperationWithProgress<TResult,TProgress>).
Also cancellation and progress is implemented in a different way (via params for .NET and interface members for WinRT).
My question is why Microsoft did implement TAP differently for .NET and WinRT. I understand that the Windows Runtime contains cleaner code than .NET. From that point of view the WinRT TAP implementation seems to be better. I also understand that asynchrony is a native part of the Windows Runtime. But why did Microsoft not change the implementation for .NET for desktop apps as well? Using interfaces is as easy as in WinRT code ...B.T.W: Does anyone know a website that explains the state machine that is compiled for the WinRT?
Saturday, August 11, 2012 12:12 PM
What you're saying is not true. I was at first confused by this too, so I wrote a blog post about it back in September 2011.
await in WinRT does use GetAwaiter(), like any other use of await. It's just that it's an extension method WindowsRuntimeSystemExtensions.GetAwaiter(), which is hidden from IntelliSense. That extension method then takes care of converting the WinRT interfaces into a form that's compatible with await.
And I certainly wouldn't say that WinRT is “cleaner” than .Net in this regard. It just has different goals and different constraints (everything has to work well from .Net, C++ and JS).
The generated state machine is explained in Jon Skeet's Eduasync part 7: generated code from a simple async method and following two parts of the series.
Saturday, August 11, 2012 2:07 PM
Thanks, svick for the explanation. That the TAP implementation for WinRT is different makes sense from the point of view that different languages must be supported.
I already knew the Eduasync page. But this explains the state machine (like all other websites I found) for .NET desktop apps, not for the WinRT. I myself decompiled a desktop sample app (using JetBrains dotPeek 1.0) to get an idea how the state machine works. I am working on that sample for the WinRT. Then I'll see how different the state machine really is.
Saturday, August 11, 2012 2:14 PMThe state machine for WinRT is exactly the same. Like I said, WinRT async methods simply use different GetAwaiter() method, but that's all the difference between using WinRT async methods and normal .Net async methods.
Sunday, August 12, 2012 8:47 AMYes. Thanks. I confirmed that decompiling an identical async method for .NET and WinRT. The result was identical apart from the different getting of the awaiter.