Tuesday, March 20, 2012

.Net 4.5 new Async Library on Visual Studio 11 beta and latest Mono

Tuesday, March 20, 2012 Posted by Andre Broers , , , , , , , 8 comments
In this post I will show an async example that runs in Visual Studio 11 beta  and in the latest Mono. The first demo is in Visual Studio.

Open Visual Studio 11 beta and create a new console app project and name it MyAsync.

Add a the Nuget package System.Json (which I don't know why it's not in the default .net 4.5 install). But hey Nuget works great!
install-package system.json

Now create a new class MyObject:
using System;

namespace MyAsync
{
    public class MyObject
    {
        public string name { get; set; }
        public string origin { get; set; }
    }
}

Now alter the main Program.cs so that is looks like the following:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Net.Http;
using System.Json;

namespace MyAsync
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("Start Main");
            Task<List<MyObject>> GetTask = GetGoogle();
            Console.WriteLine("After Main GetGoogle");
            var res = GetTask.Result;
            Console.WriteLine("After Main GetResult");
            foreach (MyObject o in res)
            {
                Console.WriteLine("{0} - {1}", o.name, o.origin);
            }
            Console.WriteLine("Press <Enter>");
            Console.ReadLine();
        } 

        static async Task<List<MyObject>> GetGoogle() 
        {
            Console.WriteLine("Start GetGoogle");
            List<MyObject> l = new List<MyObject>();
            var client = new HttpClient();
            Task<HttpResponseMessage> awaitable = client.GetAsync("http://ajax.googleapis.com/ajax/services/search/web?v=1.0&q=broersa"); 
            HttpResponseMessage res = await awaitable;
            Console.WriteLine("After GetGoogle GetAsync");
            dynamic data = JsonValue.Parse(await res.Content.ReadAsStringAsync());
            Console.WriteLine("After GetGoogle ReadAsStringAsync");
            foreach (var r in data.responseData.results)
            {
                l.Add(new MyObject() { name = r.titleNoFormatting, origin = "google" });
            }
            return l; 
        } 
    }
}

This code will do an asynchronous search on google. In line 15 it starts the search by calling GetGoogle. The result of the call is a Task. The function GetGoogle will call the GetAsync function to make an asynchronous call to get the google result. It will run until it reaches an await instruction. From here on it will continue to run the Main function until the google search results are nescessary.
C:\Users\Andre\Documents\Visual Studio 11\Projects\MyAsync\MyAsync\bin\Debug>MyAsync.exe
Start Main
Start GetGoogle
After Main GetGoogle
After GetGoogle GetAsync
After GetGoogle ReadAsStringAsync
After Main GetResult
Andre Broers' personal blog - google
EJB3 + JPA on OC4J with Client « Andre Broers' personal blog - google
BroersA Blog - google
Install VirtualBox Linux Guest Additions in Ubuntu Server | BroersA ... - google

Press Enter

We can modify the code a bit to show the asyncness even better. When we put in a sleep before line 17 .
Console.WriteLine("Before Main Sleep");
System.Threading.Thread.Sleep(5000);
Console.WriteLine("After Main Sleep");

When we run this we will see that the asynchronous code keeps running side by side of our main thread.
C:\Users\Andre\Documents\Visual Studio 11\Projects\MyAsync\MyAsync\bin\Debug>MyAsync.exe
Start Main
Start GetGoogle
After Main GetGoogle
Before Main Sleep
After GetGoogle GetAsync
After GetGoogle ReadAsStringAsync
After Main Sleep
After Main GetResult
Andre Broers' personal blog - google
EJB3 + JPA on OC4J with Client « Andre Broers' personal blog - google
BroersA Blog - google
Install VirtualBox Linux Guest Additions in Ubuntu Server | BroersA ... - google

Press <Enter>

Now it is time the run this code on Linux Ubuntu Server with our latest installed Mono on it.

Login to your linux box with the latest mono on it.
Create the two source files and paste the above code in it.
me@ubuntu01:~$ cd
me@ubuntu01:~$ mkdir MyAsync
me@ubuntu01:~$ cd MyAsync
me@ubuntu01:~/MyAsync$ vi MyObject.cs
me@ubuntu01:~/MyAsync$ vi Program.cs

Now build the application. I still had to copy the System.Json.dll assembly into the MyAsync folder in Linux. Although Mono has it's own System.Json the implementations aren't compatible yet. I used dropbox to copy from windows8 to host windows7 and pscp (putty) to copy to linux.
me@ubuntu01:~/MyAsync$ ls
MyObject.cs  Program.cs  System.Json.dll
me@ubuntu01:~/MyAsync$ mcs -r:System.Net.Http -r:System.Json Program.cs MyObject.cs
me@ubuntu01:~/MyAsync$ mono Program.exe
Start Main
Start GetGoogle
After Main GetGoogle
Before Main Sleep
After GetGoogle GetAsync
After GetGoogle ReadAsStringAsync
After Main Sleep
After Main GetResult
Press <Enter>

me@ubuntu01:~/MyAsync$

8 comments:

  1. [...] Mar 262012   In this blog I will continue with the async sample I wrote in a previous blog post. I showed the new async library of dot.net 4.5. Which will also work with Mono. All the samples I [...]

    ReplyDelete
  2. hi thanks for this, I am having problems in running this example from within my company - on the client.GetAsync(...) command I get barred by the proxy. outside the company the example works fine,
    Great! obviously I need to bypass the Proxy or supply credentials -
    can you show me how to set this up, Proxy used to be ( I thought) a property of the HttpClient Class - this is no longer there !
    many thanks

    ReplyDelete
  3. You can use the following in the app.config:

    <system.net>
    <defaultProxy enabled="true" useDefaultCredentials="true">
    <proxy usesystemdefault="True" />
    </defaultProxy>
    </system.net>

    http://msdn.microsoft.com/en-us/library/dkwyc043.aspx

    ReplyDelete
  4. Does line 35 block? I would have thought one would need the following?
    dynamic data = JsonValue.Parse(await res.Content.ReadAsStringAsync());

    ReplyDelete
  5. You are right. I changed to code. Thanks.

    ReplyDelete
  6. Good stuff. And after some further reading, calling get_Result can apparently even cause deadlock in a environment with a UI/special thread.
    http://blogs.msdn.com/b/pfxteam/archive/2011/01/13/10115163.aspx

    ReplyDelete