Async CTP Refresh - its state and direction
We really appreciate everyone who has installed the Async CTP. It has given us tremendous feedback. We appreciate all the discussion and bug reports that have come from users. We made the CTP uninstallable to encourage people to test it.
But this is just a CTP. You install it, use it and deploy apps with it at your own risk. This and the following four blog posts will give you raw information to help you make an informed judgment about the state of the CTP.
We do not provide support for the Async CTP. We wanted to get the CTP out early, and so haven't held it up to the same quality standards as we will for the final polished release of async that's coming in the next version of Visual Studio. But I'd like to point out that Microsoft has already released a polished version of "Async"...
- F# has already shipped with Async in Visual Studio 2010.
It is high quality, robust, tested, flexible, and supported by Microsoft.
I personally think F# is a great language -- ahead of the curve, so that if you learn F# then you'll be a couple of years ahead of your peers. Indeed, F# introduced Async first.
Q. What issues are there in the Async CTP?
We've discovered close to 400 bugs in async since the first CTP, thanks to feedback from early adopters and thanks to the phenomenal testers in the MS Languages QA team. I'll analyze those 400 bugs over the next four days:
- Design changes in the Async CTP Refresh
- Bugs fixed in the Async CTP Refresh
- Known and unknown bugs in the Async CTP Refresh
- Mitigations when using the Async CTP Refresh
The first Async CTP was an early branch of our main development code base. We have spent all our bug-fixing work on that main codebase, which will eventually ship with the next Visual Studio.
We have back-ported only a handful of bug-fixes from the main codebase back into the Async CTP Refresh - mainly ones to do with quality of code-generation.
Q. Why not just release a supported out-of-band Async feature already?
Q. Why delay it until the next release of Visual Studio?
Q. Why not put all the bug-fixes into the CTP Refresh?
Async is a huge feature! I think it will change the way most people program. We have to do it right, to make it consumable by everyone rather than just early-adopters. Here's some of what has to happen:
1. Language support in C# and VB
The CTP only contains about half of the language support. It doesn't yet support proper overload resolution with async lambdas, nor lambda type inference, nor async expression lambdas, nor late-bound await.
2. IDE support
Debugger support, GenerateFromUsage, Intellisense - all are absent from the CTP
3. Adding async APIs to the .NET framework
The CTP threw together a bunch of extension methods to make existing async APIs support the language feature, but we need to properly engineer all of them, and think about new APIs that should have async versions.
4. Bringing the support libraries to other platforms, such as Windows Phone 7 and Silverlight
The CTP had a provisional AsyncCtpLibrary_Silverlight.dll, and the CTP Refresh has a provisional AsyncCtpLibrary_Phone.dll, but these are not in a final state. We can make them faster and cleaner if we engineer them properly.
5. Making ASP work with async
The CTP has an ASP async sample, but we think we can bake async support more powerfully into ASP.
The CTP Refresh has a unit-testing sample, but we've put it out as an exploration of what should be done - not the final answer
7. Inventing the new design patterns for async programming, and guidance
The new style of async programming, from F# and now C#/VB, has not been used widely before. We think it will become ubiquitous. But no one yet has the programming maturity to know what are the best design practices around async. It'll take Microsoft and the wider community both time and experience before we figure out how best to use async. We can't be sure we've got the feature right until we've got more real-world experience. And we'd never want to commit something into the C#/VB languages until we're sure it's right.
In all, to do Async right we need wholesale work on all of VS and on all of .NET. It can never be done just by a CTP. It is the kind of disruptive change that requires a whole new release of VS.
Q. Will my Async CTP code still work the same when the next VS is released and I upgrade to it?
NO! Your current Async CTP Refresh code will require changes when the next VS is released and you upgrade to it... Here are the chief differences:
In the Async CTP you have to use TaskEx everywhere. In the final version, we'll be rolling all these things into the main Task class.
Overload resolution and type inference
The Async CTP does not implement overload resolution of async lambdas properly, nor type inference. If you pass an async lambda then it might pick different overloads when you upgrade to the next VS. This was a real issue for us in the CTP where we had to separate TaskEx.Run and TaskEx.RunEx to work around the overload-resolution limitations.
Order of evaluation
The Async CTP has the wrong order of evaluation for compound expressions. In particular, it evaluates all await expressions in a statement first, and then execute the rest of the statement afterwards. Thus, "if (f() && await g())" in the CTP will always evaluate g() and await it first, even if f() returns false. The next version of VS will have the correct order of evaluation. To make this fix we actually had to overhaul a large part of the codegen side of the compilers. We thought this too risky, at this stage, to back-port to the CTP Refresh.
The Async CTP uses extension methods to provide async versions of the .NET APIs. The next release of VS will have them as instance methods. Overload resolution rules treats extension methods differently from instance methods, and so the next release may cause subtle differences in overload resolution.
The Async CTP has the wrong precedence for the Await operator in VB. It should have highest precedence, but actually has lowest. For instance, "Await e + Await f" is parsed in the CTP as if it were "Await (e + Await f)," but in the final release it will parse as "(Await e) + (Await f)" .