Monday, September 28, 2009

Implementing Asynchronous Operations in WCF

Just as the WCF plumbing enables clients to call server operations asynchronously, without the server needing to know anything about it, WCF also allows service operations to be defined asynchronously. So an operation like:

        [OperationContract]

        string DoWork(int value);

…might instead be expressed in the service contract as:

        [OperationContract(AsyncPattern = true)]

        IAsyncResult BeginDoWork(int value, AsyncCallback callback, object state);

 

        string EndDoWork(IAsyncResult result);

Note that the two forms are equivalent, and indistinguishable in the WCF metadata: they both expose an operation called DoWork[1]:

image

... but in the async version you are allowing the original WCF dispatcher thread to be returned to the pool (and hence service further requests) while you carry on processing in the background. When your operation completes, you call the WCF-supplied callback, which then completes the request by sending the response to the client down the (still open) channel. You have decoupled the request lifetime from that of the original WCF dispatcher thread.

From a scalability perspective this is huge, because you can minimise the time WCF threads are tied up waiting for your operation to complete. Threads are an expensive system resource, and not something you want lying around blocked when they could be doing other useful work.

Note this only makes any sense if the operation you’re implementing really is asynchronous in nature, otherwise the additional expense of all this thread-switching outweighs the benefits. Wenlong Dong, one of the WCF team, has written a good blog article about this, but basically it all comes down to I/O operations, which are the ones that already have Begin/End overloads implemented.

Since Windows NT, most I/O operations (file handles, sockets etc…) have been implemented using I/O Completion Ports (IOCP). This is a complex subject, and not one I will pretend to really understand, but basically Windows already handles I/O operations asynchronously, as IOCPs are essentially work queues. Up in .Net land, if you are calling an I/O operation synchronously, someone, somewhere, is waiting on a waithandle for the IOCP to complete before freeing up your thread. By using the Begin/End methods provided in classes like System.IO.FileStream, System.Net.Socket and System.Data.SqlClient.SqlCommand, you start to take advantage of the asynchronicity that’s already plumbed into the Windows kernel, and you can avoid blocking that thread.

So how to get started?

Here’s the simple case: a WCF service with an async operation, the implementation of which calls an async method on an instance field which performs the actual IO operation. We’ll use the same BeginDoWork / EndDoWork signatures we described above:

    public class SimpleAsyncService : IMyAsyncService

    {

        readonly SomeIoClass _innerIoProvider = new SomeIoClass();

 

        public IAsyncResult BeginDoWork(int value, AsyncCallback callback, object state)

        {

            return _innerIoProvider.BeginDoSomething(value, callback, state);

        }

 

        public string EndDoWork(IAsyncResult result)

        {

            return _innerIoProvider.EndDoSomething(result);

        }

    }

I said this was simple, yes? All the service has to do to implement the Begin/End methods is delegate to the composed object that performs the underlying async operation.

This works because the only state the service has to worry about – the ‘SomeIoClass’ instance – is already stored on one of its instance fields. It’s the caller’s responsibility (i.e. WCF’s) to call the End method on the same instance that the Begin method was called on, so all our state management is taken care of for us.

Unfortunately it’s not always that simple.

Say the IO operation is something you want to / have to new-up each time it’s invoked, like a SqlCommand that uses one of the parameters (or somesuch). If you just modify the code to create the instance:

        public IAsyncResult BeginDoWork(int value, AsyncCallback callback, object state)

        {

            var ioProvider = new SomeIoClass();

            return ioProvider.BeginDoSomething(value, callback, state);

        }

…you are instantly in a world of pain. How are you going to implement your EndDoWork method, since you just lost the reference to the SomeIoClass instance you called BeginDoSomething on?

What you really want to do here is something like this:

        public IAsyncResult BeginDoWork(int value, AsyncCallback callback, object state)

        {

            var ioProvider = new SomeIoClass();

            return ioProvider.BeginDoSomething(value, callback, ioProvider); // !

        }

 

        public string EndDoWork(IAsyncResult result)

        {

            var ioProvider = (SomeIoClass) result.AsyncState;

            return ioProvider.EndDoSomething(result);

        }

We’ve passed the ‘SomeIoClass’ as the state parameter on the inner async operation, so it’s available to us in the EndDoWork method by casting from the AsyncResult.AsyncState property. But now we’ve lost the caller’s state, and worse, the IAsyncResult we return to the caller has our state not their state, so they’ll probably blow up. I know I did.

One possible fix is to maintain a state lookup dictionary, but what to key it on? Both the callback and the state may be null, and even if they’re not, there’s nothing to say they have to be unique. You could use the IAsyncResult itself, on the basis that almost certainly is unique, but then there’s a race condition: you don’t get that until after you call the call, by which time the callback might have fired. So your End method may get called before you can store the state into your dictionary. Messy.

Really what you’re supposed to do is implement your own IAsyncResult, since this is only thing that’s guaranteed to be passed from Begin to End. Since we’re not actually creating the real asynchronous operation here (the underlying I/O operation is), we don’t control the waithandle, so the simplest approach seemed to be to wrap the IAsyncResult in such a way that the original caller still sees their expected state, whilst still storing our own.

I’m not sure if there’s another way of doing this, but this is the only arrangement I could make work:

        public IAsyncResult BeginDoWork(int value, AsyncCallback callback, object state)

        {

            var ioProvider = new SomeIoClass();

            AsyncCallback wrappedCallback = null;

            if (callback!=null)

                wrappedCallback = delegate(IAsyncResult result1)

                                      {

                                          var wrappedResult1 = new AsyncResultWrapper(result1, state);

                                          callback(wrappedResult1);

                                      };

 

            var result = ioProvider.BeginDoSomething(value, wrappedCallback, ioProvider);

            return new AsyncResultWrapper(result, state);

        }

Fsk!

Note that we have to wrap the callback, as well as the return. Otherwise the callback (if present) is called with a non-wrapped IAsyncResult. If you passed the client’s state as the state parameter, then you can’t get your state in EndDoWork(), and if you passed your state then the client’s callback will explode. As will your head trying to follow all this.

Fortunately the EndDoWork() just looks like this:

        public string EndDoWork(IAsyncResult result)

        {

            var state = (AsyncResultWrapper) result;

            var ioProvider = (SomeIoClass)state.PrivateState;

            return ioProvider.EndDoSomething(result);

        }

And for the sake of completeness, here’s the AsyncResultWrapper:

        private class AsyncResultWrapper : IAsyncResult

        {

            private readonly IAsyncResult _result;

            private readonly object _publicState;

 

            public AsyncResultWrapper(IAsyncResult result, object publicState)

            {

                _result = result;

                _publicState = publicState;

            }

 

            public object AsyncResult

            {

                get { return _publicState; }

            }

 

            public object PrivateState

            {

                get { return _result.AsyncResult; }

            }

 

            // Elided: Delegated implementation of IAsyncResult using composed IAsyncResult

        }

By now you are thinking ‘what a mess’, and believe me I am right with you there. It took a bit of trail-and-error to get this working, it’s a major pain to have to implement this for each-and-every nested async call and – guess what – we have lots of them to do. I was pretty sure there must be a better way, but I looked and I couldn’t find one. So I decided to write one, which we’ll cover next time.

Take-home:

Operations that are intrinsically asynchronous – like IO - should be exposed as asynchronous operations, to improve the scalability of your service.

Until .Net 4 comes out, chaining and nesting async operations is a major pain in the arse if you need to maintain any per-call state.

 

Update: 30/9/2009 – Fixed some typos in the sample code

[1] Incidentally, if you implement both the sync and async forms for a given operation (and keep the Action name for both the same, or the default), it appears the sync version gets called preferentially.

Monday, September 21, 2009

Calling a WCF Service Asynchronously from the Client

In ‘old school’ ASMX web services, the generated proxy allowed you to call a service method asynchronously by using the auto-generated Begin/End methods for the operation in question. This is important for client applications, to avoid blocking the UI thread when doing something as (potentially) slow as a network call.

WCF continues this approach: if you use ‘add service reference’ with ‘Generate Asynchronous Operations’ checked (in the Advanced dialog):

image

... or SvcUtil.exe with the /a (async) option, your client proxy will contain Begin/End methods for each operation, in addition to the original, synchronous version. So for an operation like:

        [OperationContract]

        string DoWork(int value);

…the proxy-generated version of the interface will contain two additional methods, representing the Asynchronous Programming Model (APM)-equivalent signature:

        [OperationContract(AsyncPattern=true)]

        IAsyncResult BeginDoWork(int value, AsyncCallback callback, object asyncState);

 

        string EndDoWork(IAsyncResult result); // No [OperationContract] here

All it takes then to call the operation is to call the relevant Begin method, passing in a callback that is used to process the result. The UI thread is left unblocked and your request is executed in the background.

You can achieve the same result[1] with a ChannelFactory, but it takes a bit more work. Typically you use the ChannelFactory directly when you are sharing interface types, in which case you only get Begin/End methods if they are defined on the original interface – the ChannelFactory can’t magically add them. What you can do, however, is create another copy of the interface, and manually implement the additional ‘async pattern’ signatures, as demonstrated above.

Either way, what’s really important to realise here is that the transport is still synchronous. What the Begin/End methods are doing is allowing you to ‘hand off’ the message dispatch to WCF, and be called back when the result returns. And this explains why we can pull the trick above where we change the client’s version of the interface and it all ‘just still works’: from WCF’s perspective the sync and begin/end-pair signatures are considered identical. The service itself has only one operation ‘DoWork’.

And the reverse applies too. If you have a service operation already defined following the APM - i.e. BeginDoWork / EndDoWork - unless you choose to generate the async overloads your client proxy is going to only contain the sync version: DoWork(). Your client is calling – synchronously – an operation expressly defined asynchronously on the server. Weird, yes? But (as we will see later), it doesn’t matter. It makes no difference to the server.

Take-home

Clients should call service operations using async methods, to avoid blocking the UI thread. Whether the service is or isn’t implemented asynchronously is completely irrelevant[2].

[1] For completeness I should point out there are actually two more ways to call the operation asynchronously, but it all amounts to the same thing:

  • The generated service proxy client also contains OperationAsync / OperationCompleted method/event pairs. This event-based approach is considered easier to use (I don’t see it personally). Note this is on the generated client, not on the proxy’s version of the interface, so you can’t do this with a ChannelFactory (unless you implement it yourself).
  • If you’re deriving from ClientBase directly you can use the protected InvokeAsync method directly. Hardcore! This is how the generated proxy client implements the Async / Completed pattern above.

[2] …and transparent, unless you’re sharing interface types

Sunday, September 20, 2009

Tablet Netbooks

I said back in March that what I really wanted was a 10 hour tablet netbook. Well, they’re starting to come out now:

http://www.dynamism.com/viliv_s7.shtml

It’s actually too small, and not dual core (there must eventually be a netbook version of the Atom 300 yes?), but we’re so close now.

Friday, September 18, 2009

Asynchronous Programming With WCF

I’m currently spending a lot of time exposing intrinsically asynchronous server operations to a client application, and I’ve been really impressed with the way WCF caters for this. Asynchronicity is very important for performance and scalability of high-volume systems, but it’s a confusing area, and often something that’s poorly understood.

So I thought I’d write a series of posts to try and shed some light into these areas, as well as share some of the more interesting things I’ve learnt along the way.

Before we start you’ll have to have at least passing familiarity with the Asynchronous Programming Model (APM), which describes the general rules surrounding the expression of an operation as a pair of Begin/End methods. At very least, you need to get your head around the fact that these signatures:

	// sync version
int DoWork();

// async version as Begin/End pair
IAsyncResult BeginDoWork(AsyncCallback callback, object state);
int EndDoWork(IAsyncResult result);


…are equivalent.

Thursday, September 17, 2009

Christmas Come Early for Certifications

At TechEd Australia Microsoft were giving out 25% discount vouchers for certification exams, as part of a ‘get-certified’ push.

From now until Christmas you can also apply for (depending on the exam) 25%-off vouchers via this campaign site:

http://www.microsoft.com/learning/en/us/offers/career.aspx

Doesn’t seem to be any one-per-person restriction either.

Friday, September 11, 2009

TechEdAu 2009: Day 3

Highlights:

  • All the parallel tasks support in .Net 4

Lowlights:

  • No go-live licence for the parallel tasks support in .Net 4, or the existing CTPs.
  • The ‘real world’ EF talk, that blew

Update: Hey, somewhere in these last 3 posts I should have mentioned Windows Identity Foundation, which looked pretty cool (rationalizing all the claims-based identity stuff out of WCF). But I didn’t. So this’ll just have to do.

TechEdAu 2009: Day 2

Highlights:

Somewhere-in-the-middle-lights:

  • Windows API code pack: Use XP, Vista, Win7 features easily without interop, just going to cop a whole heap of if(win7) os-sniffing around anything interesting. Didn’t we get really sick of all that browser sniffing stuff?

Lowlights:

  • Diagnosing your misbehaving MDX is still too damn hard, even Darren Gosbell’s talk was really good.
  • The Claw

Wednesday, September 09, 2009

TechEdAu 2009: Day 1

Highlights:

  • Windows 7 Problem Steps Recorder: build-in screen flow capture can be used to troubleshoot – or just document – your own UIs
  • SketchFlow: Microsoft getting into the ‘paper-prototyping’ space
  • Sql 2008 R2 ‘Database Application Components’ – packages schema, logins and jobs as one deployment unit, mainly intended for dynamic virtualisation, but obvious implications for ‘over the fence’ UAT/Prod deployments (good commentary). And CEP (‘StreamInsight’) for real-time in-memory data analysis.
  • Gemini: heterogeneous data query and BI for the Excel guy. I think the business will go nuts, the question is how easy it’ll be to upscale it to SSAS when it becomes necessary. Some suggestion the Gemini code may be used to improve SSAS’s ROLAP performance.
  • Dublin: making your WF / WCF apps manageable via IIS manager, and visible to SCOM. One click admin UI to resume suspended workflows
  • Workflow: It’s back! And now looking more like SSIS than ever (variables as part of the pipeline etc..). XAML only all the way now, so no more CodeActivities, and no backwards compatibility :-/
  • Using SetToString for MDX debugging. Genius.
  • WCF for Net 4: Default bindings! Standard endpoints! Default behaviour configurations!
  • I should probably mention the free HP Mini netbook as well.
  • Printed schedule. At last.
  • Passing WCF exam

Lowlights:

  • Schedule builder designed for larger screens than HP Mini. Can we just get the data from a feed please?
  • Coffee queue
  • No pen or paper in bag
  • No outbound SMTP from the WiFi (again). IMAP users roll your eyes…

(Update 17/9: Added some hyperlinks in lieu of more detailed explanations. And realized I missed Sql CEP altogether…)

Popular Posts