Making Asynchronous WCF calls without SvcUtil

On the course of last few months, I’ve been working with Craig Neuwirt, on what I consider one of the coolest additions to Castle WCF Integration Facility.

Problem

As you probably know by default all WCF calls are synchronous – you make a request, under the cover WCF blocks your thread using a WaitHandle waiting for response, then it unblocks your threads making it look like a local call. This makes things simple for a programmer, who does not have to deal with synchronization, but it’s an overkill from scalability and performance perspective.

There are also one way calls, often mistakenly called ‘fire and forget’ which are still synchronous, but return control to your thread as soon as they get confirmation from the other end that message was received.

There are also actual asynchronous calls, but to take advantage of this you have to either use svcutil to generate your code, or build asynchronous versions of your contracts manually, which is tedious, forces you to remember quite a lot details about how asynchronous contracts should look like, and there’s no way compiler will tell you your sync and async contracts are out of sync (no pun intended).

Solution

Using trunk version of WCF Facility you can take advantage of a new mechanism that lets you perform asynchronous WCF calls having just the synchronous contract. Let me show you an example.

asyncwcf_solution

Contract project holds the service contract that both client and service share:

[ServiceContract]
public interface IMyService
{
    [OperationContract]
    string MyOperation(string message);
}

Notice there’s no asynchronous version of the operation.

Service project contains only simple implementation of the contract plus console host.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerSession)]
public class MyService : IMyService
{
    public string MyOperation(string message)
    {
        Console.WriteLine("Called non one way operation... with " + message);
        Thread.Sleep(1000);
        Console.WriteLine("Done calculating");
        return message.ToUpperInvariant();
    }
}

It uses Thread.Sleep to simulate some lengthy operation, so that we can actually see that client does not wait for the end of the operation.

The service host uses WCF Facility to configure the service:

class Program
{
    static void Main(string[] args)
    {
        using (StartService())
        {
            Console.WriteLine("Running");
            Console.ReadKey(true);
        }
    }
 
    private static IWindsorContainer StartService()
    {
        return new WindsorContainer()
            .AddFacility<WcfFacility>()
            .Register(Component.For<MyService>().ActAs(
                        new DefaultServiceModel().AddEndpoints(
                            WcfEndpoint.ForContract<IMyService>()
                                .BoundTo(new NetTcpBinding())
                                .At("net.tcp://localhost/Service"))));
    }
}

Client project is even simpler:

class Program
{
    static void Main()
    {
        var container = ConfigureContainer();
 
        var client = container.Resolve<IMyService>("operations");
        for(int i=0;i<10;i++)
        {
            Console.WriteLine("Asking: " + i);
            client.BeginWcfCall(
                s => s.MyOperation("Operation for " + i.ToString()),
                asyncCall => Console.WriteLine(asyncCall.End()),
                null);
        }
        Console.ReadKey(true);
    }
 
    private static WindsorContainer ConfigureContainer()
    {
        var container = new WindsorContainer();
        container.AddFacility<WcfFacility>().Register(
            Component.For<IMyService>()
                .Named("operations")
                .ActAs(new DefaultClientModel
                           {
                               Endpoint = WcfEndpoint.
                                   BoundTo(new NetTcpBinding()).
                                   At("net.tcp://localhost/Service")
                           }));
        return container;
    }
}

It configures Windsor container and WCF Facility, then it obtains client proxy for the service (again, synchronous contract) and uses some WCF Facility magic to perform calls asynchronously. Let’s run it and see:

asyncwcf_program

As you can see, on the client we first issued all 10 requests, then we gradually received responses from the server.

So how do I use it?

Discussion

As you can see in the code above, instead of calling MyOperation directly on proxy I used BeginWcfCall extension method from WCF Facility and passed there a delegate with invocation of the method, plus two more arguments. The second and third arguments can be either AsyncCallback, and object, like in standard .NET async pattern, or (as in my example) IWcfAsyncCall<T> (or it’s non-generic version for methods that don’t return any value).

asyncwcf_IWcfAsyncCall

IWcfAsyncCall itself inherits from IAsyncResult and adds convenience methods to end async invocation. The overload with out arguments are there to handle methods that have ref or out arguments. Yes – this means you can use that also for methods with out and ref arguments. One more noteworthy feature is usage of SynchronisationContext, which means it’s safe to update WinForms/WPF GUI from the end operation thread.

The code is available now, take it, use it, tell us what you think.

Technorati Tags: ,

WCF client proxy with Castle Dynamic Proxy

I’ve been doing a lot of work with WCF lately. It’s a great framework, and I really like it, but it has its drawbacks. First of all, it is overly complicated in certain places (security!), which makes it really hard to use sometimes. Its sheer size, makes it also hard to grasp. It has a lot of extensions points but the fact that you have to plug into them yourself adds to that complexity. It simply begs for good IoC integration.

You can partially alleviate that by using Castle WCF facility that lets you use IoC container to extend WCF, but it’s only half of the story. The other half is, that creators of WCF try very hard (and I mean, really very hard) not to allow you to do anything else than what they allow you to do. This is pretty frustrating at times, when you want to do some advanced things with it.

One such place is creation and usage of client side proxy. WCF, being all about SOAP messages is surprisingly heavily type based in this part, which does not leave you much flexibility here (this can be… hacked, but I’ll write about it in later post).

WCF client side proxies are remoting proxies. They are a thin layer around whole client WCF runtime and invocation pipeline. When you invoke a method on such proxy it gets intercepted by certain classes in WCF, based on the method you called and its parameters (and metadata on your ServiceContract type) a message is created and depending on various factors many other things happen under the cover (it’s pretty similar to how Dynamic Proxy’ interface proxies without target work).  The thing is, since it’s all private sealed and internal, you can’t really control any of it.

These two factors (strong coupling to CLR types and internal paranoia) made it very challenging when working on a feature I wanted to add to Castle WCF Facility – ability to invoke proxy methods asynchronously.

wcf_generate_async_operations

If you’re scratching your head thinking it’s hardly a new feature since you can do it already, let me explain you what I mean. Sure, you can select Generate asynchronous operations if you’re generating code for proxy, but this approach has some drawbacks. First of all, it uses code generation. Every time you change something you have to regenerate the code. Not to mention that this code is ugly as November night. The preferred approach is to factor out you contracts to separate assembly and to reuse them for both server and client (yes, this works only if both client and server use WCF).

In this case however you don’t get async methods. Turns out, you can do it without generated proxies, you have to create an async version of your interface though, and keep it in sync with the synchronous version. This is better since you control the code, you can use inheritance, it’s more compact than the generated version. You still have to create and maintain a type to satisfy weird desire of WCF to have types where type is not really needed.

Well, here’s a teaser for you:

castle_dp_WCF

I’ll blog about specifics of how the async stuff itself works in later post. Now I’ll explain how I got proxying stuff working. It’s also noteworthy that I did all that with public API only, no reflection, no IL generation – pure documented public API, which hopefully will pay back in this solution being quite stable.

To create the proxy, without codegen you use ChannelFactory<T> class, and its CreateChannel method. The method is virtual, so you can inherit from the class and get a chance to play with the proxy it creates before it’s passed the the caller.

Considering how remoting proxies are built, they consist of two parts: transparent proxy which is pure magic, and RealProxy which is just a normal CLR class. Drawing analogies to Dynamic Proxy library, RealProxy creates something similar to IInvocation, and passes it to RealProxy which acts as an IInterceptor.

I wanted to get hold of the RealProxy and swap transparent proxy with proxy generated by Dynamic Proxy. I also needed an adapter that would convert IInvocation to IMessage, which is what RealProxy uses.

Here’s the code that makes it happen

public override T CreateChannel(EndpointAddress address, Uri via)
{
    var channel = base.CreateChannel(address,via);
    IHasRealProxy proxy = new RealProxyWrapper(RemotingServices.GetRealProxy(channel));
    WCFInterceptor wcfInterceptor;
    ProxyGenerationOptions options = GetOptions(proxy, out wcfInterceptor);
    var target = _generator.CreateInterfaceProxyWithoutTarget(typeof(T), new[] { typeof(IEndAsyncCall) }, options, wcfInterceptor);
    return target as T;
}

Having transparent proxy, I use RemotingServices.GetRealProxy method to get its underlying RealProxy implementation. I then wrap the real proxy in Castle’s dynamic proxy and return it instead.

This may sound like it’s not a big deal but it has two significant implications: The whole operation is transparent to the RealProxy, the whole runtime underneath it, and the caller. Another thing – now you’re in control of the proxy. You can get into the execution pipeline and do the usual stuff dynamic proxy lets you do.

This is huge. This is what ultimately enables the async calls without having async type, which I’ll write about as soon as I clean up the code, which is now a mess. The code will probably get published as part of Castle WCF facility at some point later in time.

Technorati Tags: , ,