Async CTP Refresh - mitigations when using the CTP
The preceding four blog posts have outlined the known and unknown bug areas in the CTP. Now it's time to set out some concrete mitigation strategies.
Use F# instead
F# already shipped in VS2010 with Async support. It is tried, tested, high-quality, supported, and flexible. With F# you can go ahead writing Async code without even worrying about the CTP. F# is also a great language to learn in its own right.
Run PEVerify.exe and unit tests
Running PEVerify has caught about half of the codegen bugs we've found. You should definitely use it too.
Hint: quickly launch the "VS Command Prompt (2010)" from the start menu by typing the word "Command" in the search box and picking it from the results.
And as always, run unit tests. Most of the codegen bugs show up quite clearly even with superficial unit testing. The key bugs we found which didn't (especially the race-condition bugs) have been fixed in the CTP Refresh.
Be careful of synchronization context in async Windows Phone apps
There's a known issue on Windows Phone 7 such that any Await statements will always resume on the UI thread - even if you performed the Await on a background thread. In the CTP, the "AsyncBackgroundThread" sample shows a work-around for this issue.
Avoid complicated nested awaits
A "nested await" is an await expression that occurs as a sub-expression of another expression. A good rule of thumb is this: "If I couldn't easily have rewritten my statement by pulling out all awaits onto the preceding line, then the Async CTP might not have done it right either." For instance
// OK: SIMPLE OPERATORS IN VB+C#:
var s = await f() && await g();
// is probably safe (albeit wrong order), since it can be trusted to behave like this:
var $temp1 = await f();
var $temp2 = await g();
var s = $temp1 && $temp2;
' OK: USING CLAUSES IN VB+C#:
Using x = Await g() : ... : End Using
' is probably safe, since it can be trusted to behave like this:
Dim $temp1 = Await g()
Using x = $temp1 : ... : End Using
' USE WITH CARE, AND VERIFY+TEST: LOOPS IN VB:
While Await g() : ... : End While
' Note that it must have been more complicated than just a simple rewrite:
Dim $temp = Await g()
While temp : ... : End While
// DANGER: OTHER COMPLICATED IDIOMS IN VB+C#:
f(await g()).StructField.x = f(await g()).m(ref y, await t);
// Distrust this kind of code!
// * Avoid "await" on the left hand side of an assignment
// * Avoid combining awaits with ByRef arguments
// * Avoid invoking methods on expressions involving awaits
// * Avoid "await" inside array or object initializers
Be careful of For loops in VB, and also Select Case statements. Unit-test them thoroughly and PEVerify.
In particular, non-constant "Steps" in For statements don't work. Thanks to MattMc3 for reporting this.