Building Task Based WCF Services with Task Parallel Library

by Jeffrey Juday

Tasks and the Task Parallel Library (TPL) will soon be entering the Windows Communication Foundation (WCF) vernacular. WCF 4.5 will include Task based options, however, a WCF developer needn't wait for .NET 4.5 to leverage TPL. Jeffrey Juday shows you how to build a TPL Task based WCF Service with WCF 4.0.

Tasks and the Task Parallel Library (TPL) will soon be entering the Windows Communication Foundation (WCF) vernacular. Upcoming .NET language features will be replacing the outdated Asynchronous Programming Model (APM). WCF 4.5 will include Task based options. However, a WCF developer needn't wait for .NET 4.5 to leverage TPL. TPL Tasks shipped with .NET 4.0 and WCF 4.0 works with TPL. There are some tricks to squeezing out all potential performance and avoiding concurrency problems. Building a TPL Task based WCF Service is demonstrated in the paragraphs that follow.

Tasks and the .NET Future

Realizing that CPUs were becoming more numerous and concurrency was going to become more important; Microsoft built TPL to make concurrency easier. TPL helps a developer partition and execute an Application workload on multiple CPUs. An Application workload is partitioned into Tasks classes. The Task class is the TPL core.

Unquestionably Tasks will become more important in future .NET versions. As stated earlier, Tasks will begin to play a larger role in the next versions of the .NET Framework. A new Async language feature is built on Tasks. A new asynchronous programming model centered on Tasks will become part of everything in the .NET Framework.

Typically, a Task is not something that executes for too long nor should it be a single line of code. There are two Task types: a generic Task that returns a Result and a Task that returns no result. Since code can fault, Tasks include Exception handling support. Tasks also support operation cancellation. Some Properties and Methods on the Task class appear below.

    public class Task : IAsyncResult, IDisposable
        public Task(Action action);
        public Task(Action<object> action, object state);
        public Task(Action action, CancellationToken cancellationToken);
        public object AsyncState { get; }
        public TaskCreationOptions CreationOptions { get; }
        public static int? CurrentId { get; }
        public AggregateException Exception { get; }
        public int Id { get; }
        public bool IsCompleted { get; }
        public bool IsFaulted { get; }
        public TaskStatus Status { get; }
        public Task ContinueWith(Action<Task> continuationAction);
        public void Start();
        public void Wait();
        public void Wait(CancellationToken cancellationToken);
        public bool Wait(int millisecondsTimeout);
        public static void WaitAll(params Task[] tasks);

Tasks have other nice features. Developers can block and wait for multiple Tasks to complete before proceeding. Demonstrated later in the article are Continuations. Continuations execute a Task contingent on completing an "antecedent" Task.

Getting TPL working properly with WCF requires understanding WCF Concurrency. WCF Concurrency is housed in the ServiceBehaviors attribute.

WCF ServiceBehaviors

One of the early decisions a WCF developer makes is what to configure on a Service's ServiceBehavior attribute. Of particular interest is what to set Concurrency and Instancing levels to. Does a Service spin-up a new Service class instance each time a service is activated or should a Service use a single instance? WCF Service Instancing is mostly controlled by the ServiceBehavior InstanceContextMode and ConcurrencyMode. The ServiceBehavior configuration from the sample application appears below.

[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single, ConcurrencyMode=ConcurrencyMode.Multiple)]
public class TestServiceService : Test.WCFTPL.Server.ITestServiceContract
    public TestServiceService()
        //Change InstanceContextMode to PerCall and this gets called multiple times
        Console.WriteLine("Called TestService Constructor");

While a developer could use Tasks regardless of the ServiceBehavior settings it's important to understand ServiceBehavior, Instancing, and Concurrency dangers. One fatal Concurrency mistake developers make is improperly sharing the same piece of memory. The ServiceBehavior settings above push more instance handling into the Service Operations. Local variables almost eliminate improper sharing. Since only one instance of the Service exists a developer is forced to do more allocation locally in the Operation. For example: Choosing PerSession Instancing leaves open the temptation to share member variables inside a class Instance. Since many WCF Services have more than one operation; that means two Operations running concurrently against the same Session Instance may be unknowingly sharing a space in memory.

Properly configured ServicesBehaviors and Service architectural decisions are important to building a Task Based WCF Service. Full Task based Service benefits will not be realized unless a developer implements the WCF Asynchronous model.

Asynchronous WCF with Tasks

Typically, a WCF Service with Asynchronous Operations will be more per formant than the same Service doing Synchronous Operations. Asynchronous, when done properly, will typically tie up less IO and respond better to a workload. Unfortunately, the Asynchronous Programming Model (APM) WCF follows is difficult to follow. Most developers opt out of Asynchronous unless Asynchronous is the only route.

The Service interface implementation from the sample appears below.

[ServiceContract(Namespace = "Test.WCFTPL.Service")]
interface ITestServiceContract
    //Callback and state must be the last two.  REMEMBER parameters must match with the client interface
    [OperationContractAttribute(AsyncPattern = true, Action = "TestServiceMethod", Name = "TestServiceMethod", ReplyAction = "TestServiceMethodReply")]
    IAsyncResult BeginTestServiceMethod(RequestObj req, AsyncCallback callback, object asyncState);
    // Note: There is no OperationContractAttribute for the end method.
    ResponseObj EndTestServiceMethod(IAsyncResult result);

Only the Begin portion needs the OperationContract Attribute. The following code demonstrates doing Asynchronous with Tasks.

    #region ITestServiceContract Members
    public IAsyncResult BeginTestServiceMethod(RequestObj req, AsyncCallback callback, object asyncState)
        var task = new Task<ResponseObj>((state) =>
                SpinWait.SpinUntil(() => { return false; }, 1000);
                return new ResponseObj() { PayloadOriginal = req.Payload, PayloadResponse = "Response was " + Guid.NewGuid().ToString() };
        //When the task completes notify the callback
        task.ContinueWith((t) => { callback(t); });
        return task;
    public ResponseObj EndTestServiceMethod(IAsyncResult result)
        var task = (Task<ResponseObj>)result;
        return task.Result;

Admittedly this is still more complicated than the synchronous model. However, the Task implementation is more self-contained, a bit easier to follow, and a little less clumsy.

The Task delegate is contained within a Closure. Task.Start does not immediately execute the Task. Instead, Start queues the Task to run in the .NET Thread Pool. Task implements the IAsyncResult interface. IAsyncResult is the core of the Asynchronous Programming Model. Creating the task with the object state parameter tucks the State away inside the Task class until it is needed again for the "End" portion in the operation.

Continuations are the key to making Asynchronous easier. Continuations are invoked when the Task they're attached to completes. A complete review of Continuation options is beyond the scope of this article, but you'll find more under the resource sections. When the task completes, the Continuation Task is scheduled to run. The Continuation invokes the callback and the WCF infrastructure, in turn, invokes the End Method.

End method unpacks the Result property from the completed Task and returns the result. WCF takes over from there, pushing the serialized class out of the Service operation.


Asynchronous WCF code is more per formant than synchronous code. Tasks and the Task Parallel Library can make handling Asynchronous code easier. However, before using Tasks with WCF a developer should understand how WCF configurations can impact a Task based solution.


"Sessions, Instancing, and Concurrency"

"What's new in .NET 4.5 for Parallelism"

"Understanding Tasks in .NET Framework 4.0 Task Parallel Library"


Special thanks to Stephen Toub with Microsoft.

This article was originally published on Wednesday Mar 7th 2012
Mobile Site | Full Site