Building Task Based WCF Services with Task Parallel Library

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.

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.

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.

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")]
interfaceITestServiceContract
{
//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.

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.

Conclusion

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.

Resources

Acknowledgements

Special thanks to Stephen Toub with Microsoft.

About the Author

Jeffrey Juday

Jeff is a software developer specializing in enterprise application integration solutions utilizing BizTalk, SharePoint, WCF, WF, and SQL Server.
Jeff has been developing software with Microsoft tools for more than 15 years in a variety of industries including: military, manufacturing, financial services, management consulting, and computer security.
Jeff is a Microsoft BizTalk MVP.
Jeff spends his spare time with his wife Sherrill and daughter Alexandra.

Top White Papers and Webcasts

When individual departments procure cloud service for their own use, they usually don't consider the hazardous organization-wide implications. Read this paper to learn best practices for setting up an internal, IT-based cloud brokerage function that service the entire organization. Find out how this approach enables you to retain top-down visibility and control of network security and manage the impact of cloud traffic on your WAN.

U.S. companies are desperately trying to recruit and hire skilled software engineers and developers, but there is simply not enough quality talent to go around. Tiempo Development is a nearshore software development company. Our headquarters are in AZ, but we are a pioneer and leader in outsourcing to Mexico, based on our three software development centers there. We have a proven process and we are experts at providing our customers with powerful solutions. We transform ideas into reality.