Sony Arouje Blog

a programmer's log

Making Async calls in Silverlight using Reactive Extension (Rx)

with 4 comments

In this blog I am going to explain briefly about how to make async calls using Reactive Extension (Rx). Every one knows that Silverlight is one of the best platform to create RIA’s. One of the architecture constrain of Silverlight is, it wont directly interact with backend DB. So we need to have a webservice to perform the db operations. Silverlight can consume WCF or asmx service, but their is a catch silverlight can only communicate to webservices asynchronously. We all know that async calls have several advantages. One key feature of async call is, it wont block the UI while performing the call. But one downside in async programming is the coding pattern involved in placing async calls. When I place an async calls, I use an anonymous delegate approach or use lambda expression. But some how I am not satisfied with any of these approaches, I feel my code is not clean. So we always look for a better approach and our long waiting is over with the introduction of Reactive Extension (Rx) from MS labs.

You can visit Rx web site to get more details. I am not a person to explain the architecture or indepth details of Rx instead I am going to show how it benefit me in my async programing. I am going to rewrite one of my application I wrote to upload images using Silverlight and WCF, you can get more details of that app from my blog. I will rewrite only the part where I make async calls to server to get images from WCF service. Before get into refactoring, We need to download and install the Rx libraries from Rx web site.

Let’s refactor the code to make our async calls using Rx. We need to add couple of assembly references to add Rx to Silverlight, below are those assemblies.

  • System.Observables
  • System.CoreEx
  • System.Reactive

I demonstrated two ways of interacting with WCF service in the source code I uploaded. A proxy and proxy less approach. We all know the proxy approach, the communication to the service using the class generated by VS. In one of my post I provided some insight of Proxy less approach, you can check it out here.

If you have my source code in hand, have a look at the ImageListViewModel.cs in Silverlight app. You can see how I am making the async call.

In proxy less approach I use lambda expression to make the call.

IImageServiceAsync imgService = ServiceChannelProvider.CreateChannel<IImageServiceAsync>();
imgService.BeginGetAllImage(save =>
{
    try
    {
        imgs = imgService.EndGetAllImage(save);
        this.AddToUserLogoList(imgs);
    }
    catch (Exception ex)
    {
        throw;
    }
}, imgService);

In proxy approach I used a event driven approach as shown below.

ImageServiceClient imgClient = new ImageServiceClient();

imgClient.GetAllImageCompleted += new EventHandler<GetAllImageCompletedEventArgs>(imgClient_GetAllImageCompleted);
imgClient.GetAllImageAsync();

 

void imgClient_GetAllImageCompleted(object sender, GetAllImageCompletedEventArgs e)
{
    for (int i = 0; i < e.Result.Length; i++)
    {
        this.UserLogos.Add(e.Result[i]);
    }
    NotifyOfPropertyChange(() => UserLogos);
}

 

I am not going to explain the downside of these approaches mentioned above, Just like me you all might have experienced it. Lets rewrite the code using Reactive Extension (Rx).

Proxy less approach

private void ReadAllImages()
{
    IImageServiceAsync imgService = ServiceChannelProvider.CreateChannel<IImageServiceAsync>();
    var func = Observable.FromAsyncPattern<IList<UserImage>>(imgService.BeginGetAllImage, imgService.EndGetAllImage)
        .Invoke()
        .SubscribeOnDispatcher()
        .Subscribe(s => this.UserLogos = s.ToList<UserImage>());
}

Rx have one method called FromAsyncPattern, there we can provide our Beginxxx and Endxxx functions. I provided BeginGetAllImages and EndGetAllImages to FromAsyncPattern function. I also provided the return type of EndGetAllImages() to FromAsyncPattern function. Return type of EndGetAllImages is IList<UserImage>, so I called FromAsyncPattern as FromAsyncPattern<IList<UserImage>>. Rx uses Observer pattern to publish the result. So here I added UserLogos properties as my observer, once the execution is done the result will be pushed to the observer. Here the observer is a property in my view model. Below is the UserLogos property

List<UserImage> _logos = new List<UserImage>();
public List<UserImage> UserLogos
{
    get { return _logos; }
    private set
    {
        lock (this)
        {
            _logos = value;
            NotifyOfPropertyChange(() => UserLogos);
        }
    }
}

 

Let’s see how we can make an async call in proxy generated approach.

private void ReadAllImages()
{
    ImageServiceClient imgClient = new ImageServiceClient();
    var o = Observable.FromEvent<GetAllImageCompletedEventArgs>(imgClient, "GetAllImageCompleted")
        .ObserveOn(Scheduler.ThreadPool)
        .Select(result => result.EventArgs.Result)
        .Subscribe(s => this.UserLogos = s.ToList<UserImage>());
    imgClient.GetAllImageAsync();
}

Here I used FromEvent function provided by Rx instead of FromAsyncPattern. FromEvent accepts the event type, here it is GetAllImageCompletedEventArgs. It also accepts the service client object and which event it should handle. I passed the GetAllImageCompleted to the FromEvent function. Then we need to attach UserLogos as observer. After that we called GetAllImageAsync of service proxy.

You can see our code is pretty clean, we don’t have any messy code that we normally write to handle the async calls. Once you start using Rx I think you will never go back to the old approach of placing async calls.

About these ads

Written by Sony Arouje

October 31, 2010 at 12:06 pm

4 Responses

Subscribe to comments with RSS.

  1. Hi

    Do you have a VS example solution for this, I’m having some problems ?
    Thanks

    Rory

    September 21, 2011 at 3:50 pm

    • Hi Rory,
      For this post I used a tracer created for another post and you can find the post here http://sonyarouje.wordpress.com/2010/10/01/proxy-less-silverlight-wcf-communication/. Download that tracer and do the necessary change I mentioned in this post. I will try to get the complete project for you, mean while try the approach I mentioned.

      Regards,
      Sony Arouje

      Sony Arouje

      September 21, 2011 at 4:58 pm

      • The problem is that the RX assemblies are now a different version so
        Observable.FromEvent is no longer supported…well I think that’s the issue

        Rory

        September 22, 2011 at 10:00 pm

  2. Thanks, will do :-)

    Rory

    September 22, 2011 at 9:47 pm


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.

Join 163 other followers

%d bloggers like this: