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: ,

Posted 08-09-2009 12:50 PM by Krzysztof Koźmic
Filed under: ,

[Advertisement]

Comments

DotNetShoutout wrote Making Asynchronous WCF calls without SvcUtil - Krzysztof Kozmic - Devlicio.us
on 08-09-2009 7:41 PM

Thank you for submitting this cool story - Trackback from DotNetShoutout

Tuna Toksoz wrote re: Making Asynchronous WCF calls without SvcUtil
on 08-10-2009 2:25 AM

WcfFacility is one of the coolest parts in Castle project! Keep up the good work!

I really liked the syntax, btw!

9eFish wrote Making Asynchronous WCF calls without SvcUtil - Krzysztof Kozmic - Devlicio.us
on 08-10-2009 9:46 PM

9efish.感谢你的文章 - Trackback from 9eFish

Steve wrote re: Making Asynchronous WCF calls without SvcUtil
on 03-18-2010 8:25 PM

how does this work with the wcfintegration in the svc markup?

ie.

Factory="Castle.Facilities.WcfIntegration.DefaultServiceHostFactory

is the svc not needed?  this part is confusing - ie. I see your console app , what about a wcf service hosted in iis ?

Steve wrote re: Making Asynchronous WCF calls without SvcUtil
on 03-19-2010 12:40 AM

Nevermind, I was looking at server instead of client  :)

When injected into a constructor, these async methods are not available ?

How can I use the when injected to resolve with these added calls?

Thanks

Steve wrote re: Making Asynchronous WCF calls without SvcUtil
on 03-19-2010 1:00 AM

I figured it all out.

I didn't add

using Castle.Facilities.WcfIntegration;

so I didn't see the extensions.

Thanks  :)

About The CodeBetter.Com Blog Network
CodeBetter.Com FAQ

Our Mission

Advertisers should contact Brendan

Subscribe
Google Reader or Homepage

del.icio.us CodeBetter.com Latest Items
Add to My Yahoo!
Subscribe with Bloglines
Subscribe in NewsGator Online
Subscribe with myFeedster
Add to My AOL
Furl CodeBetter.com Latest Items
Subscribe in Rojo

Member Projects
DimeCasts.Net - Derik Whittaker

Friends of Devlicio.us
Red-Gate Tools For SQL and .NET

NDepend

SlickEdit
 
SmartInspect .NET Logging
NGEDIT: ViEmu and Codekana
LiteAccounting.Com
DevExpress
Fixx
NHibernate Profiler
Unfuddle
Balsamiq Mockups
Scrumy
JetBrains - ReSharper
Umbraco
NServiceBus
RavenDb
Web Sequence Diagrams
Ducksboard<-- NEW Friend!

 



Site Copyright © 2007 CodeBetter.Com
Content Copyright Individual Bloggers

 

Community Server (Commercial Edition)