Jan
5
2012

Extending existing .NET API to support asynchronous operations

Palmier sur la plage de la grande anse du diamant

The other day I needed a way in a project I am working on to turn a .NET API, RestSharp to name it, so that I could use it in an asynchronous way.

The goal was to have the API returning a Task<TResult> so that I could use it if I want with the Async CTP. I also wanted to have something running both on .NET 4.0 and on Windows Phone 7.5. 

To achieve this goal I used

TaskCompletionSource<TResult> Class

.NET Framework 4

and defined two helper extension methods on the RestClient class of RestSharp as this:

#region using

using System;
using System.Threading;
using System.Threading.Tasks;
using RestSharp;

#endregion

namespace Sharper
{
    public static class RestClientExtensions
    {
        public static Task<TResult> ExecuteTask<TResult>(this RestClient client,
                                                         RestRequest request) where TResult : new()
        {
            var tcs = new TaskCompletionSource<TResult>();

            WaitCallback
                asyncWork = _ =>
                                {
                                    try
                                    {
                                        client.ExecuteAsync<TResult>(request,
                                                                     response => tcs.SetResult(response.Data));
                                    }
                                    catch (Exception exc)
                                    {
                                        tcs.SetException(exc);
                                    }
                                };

            return ExecuteTask(asyncWork, tcs);
        }

        public static Task<TResult> ExecuteTask<T, TResult>(this RestClient client,
                                                            RestRequest request,
                                                            Func<T, TResult> adapter) where T : new()
        {
            var tcs = new TaskCompletionSource<TResult>();

            WaitCallback
                asyncWork = _ =>
                                {
                                    try
                                    {
                                        client.ExecuteAsync<T>(request,
                                                               response =>
                                                               tcs.SetResult(adapter.Invoke(response.Data)));
                                    }
                                    catch (Exception exc)
                                    {
                                        tcs.SetException(exc);
                                    }
                                };

            return ExecuteTask(asyncWork, tcs);
        }

        private static Task<TResult> ExecuteTask<TResult>(WaitCallback asyncWork,
                                                          TaskCompletionSource<TResult> tcs)
        {
            ThreadPool.QueueUserWorkItem(asyncWork);

            return tcs.Task;
        }
    }
}

Now I can write asynchronous code like this:

public Task<List<Project>> GetAllProjects()
{
    var request = new RestRequest { Resource = "/httpAuth/app/rest/projects", RootElement = "project" };
    request.AddHeader("Accept", "application/json");

    return _restClient.ExecuteTask<List<Project>>(request);
}

So TaskCompletionSource<T> is a nice class to know about!

You might also watch this short video by Phil Pennington to get a better idea about it:

Add comment

  Country flag

biuquote
  • Comment
  • Preview
Loading

About Laurent

Laurent Kempé

Laurent Kempé is the editor, founder, and primary contributor of Tech Head Brothers, a French portal about Microsoft .NET technologies.

He is currently employed by Innoveo Solutions since 10/2007 as a Senior Solution Architect and certified Scrum Master.

Founder, owner and Managing Partner of Jobping, which provides a unique and efficient platform for connecting Microsoft skilled job seekers with employers using Microsoft technologies.

Laurent is awarded by Microsoft since Avril 2002: Most Valuable Professional (MVP).

MVP
Certified ScrumMaster
JetBrains Academy Member

My status

Twitter

Flickr

www.flickr.com
This is a Flickr badge showing public photos and videos from Laurent Kempé. Make your own badge here.

Month List

Page List