What about WCF 4.5 and the async/await pattern?
From what I’ve heard it should be pretty smooth to produce asynchronous server/client code with .net 4.5, so let’s try it out! Defining async methods on the service contract is now a lot cleaner :
[ServiceContract] public interface IPeopleService { [OperationContract] Task<IList<Person>> GetPeople(); }
instead of the wcf 4.0 way which would look something like this :
[ServiceContract] public interface IPeopleService { [OperationContract(AsyncPattern=true)] IAsyncResult BeginGetPeople(AsyncCallback cb, object state); [OperationContract] IList<Person> GetPeople(); [OperationContract] IList<Person> EndGetPeople(IAsyncResult ar); }
the server side implementation of the operation when returning a task is straightforward :
public async Task<IList<Person>> GetPeople() { Task t1 = Task.Delay(500); Task t2 = Task.Delay(500); await Task.WhenAll(t1, t2); return await Task.Factory.StartNew(() => people); }
If you don’t want to await something in the method you can skip the async keyword and still return a Task as shown below, async on a method simply tells the compiler that “I’m going to await something in this method”.
public Task<IList<Person>> GetPeople() { return Task.FromResult(people); }
Anyways it’s really nice to skip the non-implemented begin/end methods on the server which was simply boiler plating in .net 4.0. For the sake of simplicity the service will be hosted in a console application and for consuming the service I’ve implemented a simple proxy that inherits ClientBase<TChannel> and implements the contract. See the code if this confuses you (which probably means that you’re a noob ;-)). The client code when working with tasks is clean and straightforward as well :
var serviceProxy = new PeopleServiceProxy("PeopleServiceEndpoint"); Task<IList<Person>> people = serviceProxy.GetPeople(); people.ContinueWith( x => { foreach (Person person in x.Result) { Console.WriteLine( "{0} {1} born {2}", person.FirstName, person.LastName, person.BirthDate.ToShortDateString()); } });
We can control on which thread we will continue by passing in a TaskScheduler. So far so good, so what about testing? I’m using Nunit which integrates really well with VS when using resharper. I want to write an integration test (not unit) to make sure everything works well including the WCF part since unit testing my simple service is too easy ;-) I’ll host the service in the Setup method and take it down in the teardown. A simple test then looks like :
[Test] public void ShallBeAbleToGetDateTimeFromService() { IPeopleService serviceProxy = new PeopleServiceProxy("PeopleServiceEndpoint"); Task<IList<Person>> getPeopleTask = serviceProxy.GetPeople(); getPeopleTask.Wait(); IList<Person> result = getPeopleTask.Result; Assert.IsNotNull(result); Assert.AreEqual(2, result.Count); (serviceProxy as IDisposable).Dispose(); }
Obviously we’d use facades to call on services in a real application but the principle is the same. It doesn’t get much cleaner than this imo.
/A
Leave a Reply
Want to join the discussion?Feel free to contribute!