Asynchronous Web Service Implementation

In my last post I demonstrated different ways to invoke a web service asynchronously in a WPF smart client application. It’s also possible to implement the service itself using the asynchronous pattern.

For this example I will create a Baroque service. The contract for this service contains two operations: GetComposers and GetCompositions. GetComposers returns a list of Baroque era music composers via an array of Composer types. Composer is declared as a data contract that contains members for a unique numeric id, first, middle and last names.

GetCompositions returns a collection of well known compositions of a given composer. It takes the composer’s numeric id as a parameter and returns an array of string. The service contract would normally be declared as follows for a synchronous implementation.

[ServiceContract(Namespace = "https://patconroy.wordpress.com/service")]
public interface IBaroque
{
    [OperationContract]
    Composer[] GetComposers();

    [OperationContract]
    string[] GetCompositions(int composerId);
}

I’ll demonstrate later that this is how the client will see the service contract, but it must be declared differently on the back-end for asynchronous operation.

[ServiceContract(Namespace="https://patconroy.wordpress.com/service")]
public interface IBaroque
{
    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginGetComposers(AsyncCallback callback, object asyncState);
    Composer[] EndGetComposers(IAsyncResult result);

    [OperationContract(AsyncPattern=true)]
    IAsyncResult BeginGetCompositions(int composerId, AsyncCallback callback, object asyncState);
    string[] EndGetCompositions(IAsyncResult result);
}

First of all each operation is now implemented as a pair of Begin/End methods and some additional parameters were introduced. This follows the standard .NET asynchronous pattern, so it should look familiar. Additionally the AsyncPattern property of the OperationContract attribute must be set to true.

Since I’m implementing the async pattern rather than just using it I created a helper class that implements the IAsyncResult interface. This will be returned by the two Begin methods and will subsequently be passed back to the End methods. This class can hold and application state data that’s needed between the Begin and End calls. The class also includes a ManualResetEvent that gets set when the asynchronous operation completes

public class AsyncResult : IAsyncResult
{
    private object _state;
    private AsyncCallback _callback;
    private ManualResetEvent _event;

    public AsyncResult(AsyncCallback callback, object state)
    {
        _callback = callback;
        _state = state;
        _event = new ManualResetEvent(false);
    }

    #region IAsyncResult Members
    public object AsyncState
    {
        get { return _state; }
    }

    public WaitHandle AsyncWaitHandle
    {
        get { return _event; }
    }

    public bool CompletedSynchronously
    {
        get { return false; }
    }

    public bool IsCompleted
    {
        get { return _event.WaitOne(0, false); }
    }
    #endregion

    public void Complete()
    {
        _event.Set();
        if (_callback != null)
            _callback(this);
    }
}

To implement this solution I created and Access database named baroque.mdb that has two tables: Composer and Composition. Composer has a unique id column as well as the first, middle and last name text columns. Composition has the composer id and composition name columns. As you might guess there is a one-to-many relationship between composer and composition. This example used the OLE-DB data provider to read the table.

public IAsyncResult BeginGetComposers(AsyncCallback callback, object asyncState)
{
    TypedAsyncResult<Composer&#91;&#93;> result = new TypedAsyncResult<Composer&#91;&#93;>(callback, asyncState);
    ThreadPool.QueueUserWorkItem(new WaitCallback(GetComposers), result);
    return result;
}

public Composer[] EndGetComposers(IAsyncResult result)
{
    TypedAsyncResult<Composer&#91;&#93;> asyncResult = result as TypedAsyncResult<Composer&#91;&#93;>;
    if (result != null)
    {
        asyncResult.AsyncWaitHandle.WaitOne();
        return asyncResult.Result;
    }
    return null;
}

As you can, see the Begin operation sends the work to a background thread. GetComposers isn’t listed here but it’s in the code download. The framework calls the End method. You don’t do that at all. TypedAsyncResult is a specialization of AsyncResult that stores a generic operation result. It’s in the code download. BeginGetCompositions and EndGetCompositions are implemented similarly.

What is the benefit of the extra coding that was done here? For this example there really isn’t one. The OLE-DB data provider only supports synchronous database operations, so I had to create my own background thread. The SQL Server data provider, on the other hand, does support asynchronous operations. Had I used SQL Server instead of Access then I would have used SqlCommand.BeginExecuteReader and SqlCommand.EndExecuteReader. Background threading is handled in the framework rather than in the application.

WCF hides all of these implementation details from the client. The client only sees GetComposers and GetCompositions methods as if they were synchronous implementations. Of course the WCF client proxy can optionally contain the methods needed to call the service asynchronously. I described these in my last post. These are, however, independent of the server implementation. The client can choose to call the service synchronously or asynchronously regardless of how the service was coded. The code download contains a WPF client application that uses the event based asynchronous pattern to call the service.

composerclient

All of the source code from this post can be downloaded here.

Advertisements

1 Response to “Asynchronous Web Service Implementation”



  1. 1 RESTful Web Service in WCF « Discovering .NET Trackback on February 19, 2009 at 2:58 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




February 2009
M T W T F S S
« Jan   Mar »
 1
2345678
9101112131415
16171819202122
232425262728  
I am a part of all that I have met;
Yet all exprience is an arch whitherthro'
Gleams that untravell'd world, whose margin fades
For ever and for ever when I move.
How dull it is to pause, to make an end,
To rust unburnish'd, not to shine in use!
Alfred, Lord Tennyson

%d bloggers like this: