Visual Studio 11 beta is taunting you, with its new support for async and await keywords. All you have been wanting to do is use those keywords to finally clean up the mess you produced building an API that is completely async. Sadly, there’s no way you are going to be able to use the keywords until the third party tools, you are using are updated or your boss tells you that Visual Studio 11 is RTM and can be used in the company.
This is the scenario where I am in right now, well for the first part that is. The second part is not a problem, since at the office we’ve already ditched Visual Studio 2010 and moved on to Visual Studio 11 for its new build features and TFS server features. However if you’re like me, doing Mono for Android development you might want to read on.
What is async/await?
For those developers that read this post and think: “What the .. is async/await?”. These new keywords have been added to the C# 5.0 spec to make working with asynchronous tasks alot easier. Take for example, the following code:
It starts a task, waits for it to complete and executes some finalizer code to process the results of the task. This stuff is very common when you are writing async API calls with the C# 4.0 tooling. This gets messy very quickly, as the following piece of junk code demonstrates:
This could also be written alot shorter using the async and await keywords. The important bit is the await keyword. Everytime you have to for example write
You can replace this code with the following snippet using await.
The await keyword is a marker for the compiler to generate the code you wrote earlier. Although it will not generate the exact same thing, it will reproduce the behavior. If you take a look at the code using Reflector or JustDecompile after it is compiled, you will see the ContinueWith statements and other infrastructure to produce the correct behavior.
The key to making the snippets work with the new C# 5.0 spec based compiler is to use the async keyword in the method declaration in which you are going to use the await keyword. This way the compiler knows the method should be split into several parts, depending on where the await keyword is used. Everything before the line with the await keyword is placed in one method, the code that comes after the await marked line, is added to a callback method that is invoked when the task completes.
This very short and technical explanation is all in here to give you an idea of how cool these new keywords actually are. Instead of writing alot of complex code, I can just use the await keyword and the messy work is done for me. Simple as that.
Now tell me how to get it to work for my project
Although it is a feature of the new .NET framework 4.5, you can use the keywords today by following this guide.
Please note! Replacing the default compiler for your project is generally not a good idea just for the sake of using a different compiler. The code produced by other compilers might produce different results at runtime. Especially the performance of your code may be different. Also, the trick I use is not supported! I am not going to help fix a problem, because you replaced your compiler.
Download the Mono 2.11 tools
First things first, download the Mono 2.11 tools. This is a alpha release of the Mono framework, but it does work pretty good already. And besides the compiler, you will not be using anything from this framework. So don’t worry about the issues with the base class library of Mono. We skip all that
The Mono 2.11 release supports the new C# 5.0 language profile thus supports the async and await keywords.
Download the tools here and install them on your computer.
Heads up! Don’t worry if you can’t get 2.11, but only a higher release. 2.11 is the minimum version, everything above that is fine to use for this purpose.
Break open your C# project
The second step is to add a littlebit of configuration to your C# project. Microsoft did something very useful in their standard C# targets. Everytime the CSC tool is invoked, it is done so using a couple of properties.
- CscToolPath \u2013 The directory where to find the CSC.exe tool
- CscToolExe \u2013 The filename of the executable that is the C# compiler
Another cool thing is that they don’t set these properties themselves. If the properties are empty, the defaults of the .NET framework SDK are applied. However when you configure these properties in your C# project file, you can override the defaults.
So in order to use the Mono compiler you need to add a couple of properties to your .csproj file. You can either use Notepad.exe to edit the project file. Or you can right-click the project in Visual Studio and select Unload project. Once you’ve done that, you can edit the project file by right-clicking it again and selecting Edit project file.
Add the following snippet to your project file.Anywhere is fine as long as it’s somewhere after one of the other propertygroup elements.
Make sure you have the right directory (X86/x64), save the project file and reload the project in Visual Studio. That’s it, you’re good to go!
Notice: Wondering what the other properties are? As I said before, a different compiler may do different things. The Mono compiler doesn’t support all the commandline switches, so I had to override those too. Visual Studio will respond a little bit differently, but that’s it.
I tried applying the same trick to other platforms such as Windows Phone, but unfortunately it didn’t work out. I think this is due to the fact that I run Visual Studio 11 side-by-side with Visual Studio 2010. Visual Studio 11 has overwritten some target files and other things in the .NET framework directory. Because I run Visual Studio 11, I get an extra commandline switch /highentropyVA+ which is there to enable for better memory address randomization in the Windows Kernel. Adding this setting guards the application against common memory related vulnerabilities.
I might be able to get around this limitation, but for now it’s only possible to use async and await in combination with Mono for Android and Visual Studio 2010 or of course Visual Studio 11 and the new .NET framework.