Adding async\/await support to your Mono for Android projects

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\u2019s 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.<\/p>

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\u2019ve already ditched Visual Studio 2010 and moved on to Visual Studio 11 for its new build features and TFS server features. However if you\u2019re like me, doing Mono for Android development you might want to read on. <\/p>

What is async\/await?<\/h2>

For those developers that read this post and think: \u201cWhat the .. is async\/await?\u201d. 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:<\/p>

class Program 
{ static void Main(string[] args) { var fibonnaciTask = FibonnaciAsync(100).ContinueWith(task => { Console.WriteLine("Outcome: {0}",task.Result); });

    fibonnaciTask.Wait();
}

private static Task&lt;int&gt; FibonnaciAsync(decimal n)
{
    return Task.Factory.StartNew(() =&gt; Fibonacci(n));
}

private static int Fibonacci(decimal n)
{
    if(n == 0)
    {
        return 0;
    }

    if(n == 1)
    {
        return 1;
    }

    return Fibonacci(n - 1) + Fibonacci(n - 2);
}

} <\/pre>

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:<\/p>

public Task RefreshAsync() 
{ _isRefreshing = true;

var retrieveResultTask = _dataProvider.GetAsync&lt;TEntity&gt;(
    _dataProviderParameters.ServiceUri,
    _dataProviderParameters.OperationName,
    _dataProviderParameters.OperationParameters);

return retrieveResultTask.ContinueWith(task =&gt;
{
    if (task.Exception == null)
    {
        \/\/ Save the entities in the data source for quick access
        _entities.Clear();

        foreach (var entity in task.Result)
        {
            _entities.Add(entity);
        }

        \/\/ Clear the entity set and attach the new set of retrieved entities
        var entitySet = _dataContext.GetEntitySet(typeof(TEntity));

        if (entitySet == null)
        {
            throw new InvalidOperationException(
                "Cannot attach the entities to the data context. " +
                "There's no entity set supporting this type of entity.");
        }

        \/\/ Attach the entities to the data context.
        entitySet.Attach(task.Result);
    }
    else
    {
        throw task.Exception;
    }

    _isRefreshing = false;
});

} <\/pre>

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 <\/p>

var fibonnaciTask = FibonnaciAsync(100).ContinueWith(task => 
{ Console.WriteLine("Outcome: {0}",task.Result); }); <\/pre>

You can replace this code with the following snippet using await.<\/p>

 <\/p>

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.<\/p>

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.<\/p>

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.<\/p>

Now tell me how to get it to work for my project<\/h2>

Although it is a feature of the new .NET framework 4.5, you can use the keywords today by following this guide.<\/p>

Please note! <\/strong>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.<\/p>

Download the Mono 2.11 tools<\/h3>

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\u2019t worry about the issues with the base class library of Mono. We skip all that Glimlach<\/p>

The Mono 2.11 release supports the new C# 5.0 language profile thus supports the async and await keywords.<\/p>

Download the tools here<\/a> and install them on your computer.<\/p>

Heads up! <\/strong>Don\u2019t worry if you can\u2019t get 2.11, but only a higher release. 2.11 is the minimum version, everything above that is fine to use for this purpose.<\/p>

Break open your C# project<\/h3>

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. <\/p>

About this article

  • Published:
  • Tags:

Share this post

About the author

Willem Meints

Developing mobile apps, Web 2.01 proof and CSS 3.x enabled. And all that as a human being.

About this weblog

This blog is my personal spot where I talk technology. I love to hack and design pieces of technology.

I update this spot on a regular basis, to share some of my ideas and whacky contraptions for you to enjoy.

RSS Feed