Happy Birthday Async
• CommentsToday I’d like to say happy birthday to the C# async
and await
keywords! They officially turn five years old today! C# and VB both officially adopted them on September 12, 2012.
The async
and await
keywords themselves have a slightly longer history; they were originally introduced in F# on April 12th, 2010. async
slowly moved into C#/VB, and from there they spread to Python, TypeScript, Hack, Dart, and (recently) JavaScript. Python was a huge win for async
; the Python community is quick to pick up (or invent) the best language features, and they have one of the best language-improvement processes out there. Also, I find the Hack adoption particularly amusing - I mean, even PHP has async
these days!
The jury is still out on whether C++ will pick up async
, and Java just seems to move at a snail’s pace these days.
Remembering Ye Olde Async Days
My original intro to async
/await
post went live on my blog about five and a half years ago! It’s still fully relevant, which is unusual for a five-year-old blog post. And even today, it brings more traffic to my blog than any other post (about 15% of all my blog traffic is just for that one post).
My, how much has changed since that blog post was published! At that time, async
was an experimental language modification that required you to install a Community Technology Preview (read: unsupported) package that changed the compilers and language features used by Visual Studio 2010. That is, unless you already installed updates to VS2010, in which case the Async CTP installation would just not work. Until they fixed it, and then it worked. Until the next VS2010 update, when it broke again. No, seriously, it was that bad! :)
Oh, and once (if) you managed to get the Async CTP installed, there were still a number of bugs. And if you encountered them, there wasn’t much you could do about it: the resolution was essentially “don’t do that.” Of particular note was using multiple await
s in expressions, like Lucian’s example var x = await f() + await g();
Yeah, that didn’t even work. Your rule-of-thumb was one await
per statement, and it was best if that statement did nothing else. var fx = await f(); var gx = await g(); var x = fx + gx;
FTW!
Also, overload resolution wasn’t quite right, especially for asynchronous delegate types. But there were no async
lambdas anyway. And there was no dynamic
compatibility with await
at all. And a lot of compiler safeguards were missing (e.g., async void Main
was allowed). And the debugger support was horrible - really, there was no debugging support at all back then.
Today, async
is truly a first-class citizen of C# and VB. With every release of Visual Studio, the debugger support for async
code gets better and better. Tracing systems like Application Insights “just work” coordinating traces across asynchronous code. We recently got value-type Task<T>
equivalents, and new enhancements are on the horizon: better code generation around the async
state machine, async
enumerators, … the future is bright!