.NET Framework 4.0 Task Parallell Library vs. the Concurrency and Coordination Runtime

Introduction

I really love Concurrency and Coordination Runtime (CCR) and I have a major product built around CCR. Ever since the .NET Framework 4.0 Task Parallel Library (TPL) was released, I've been contemplating moving off of CCR.

There are some compelling reasons to consider adopting TPL over CCR. For example, TPL is part of the .NET Framework and some tools in Microsoft Visual Studio center around TPL. Therefore, standardizing on the new patterns and practices supported by the .NET Framework and Visual Studio may be better than adopting a product unknown to the typical .NET developer. CCR may also be overkill if a developer simply wants to handle some asynchronous work.

Unfortunately, choosing between adopting CCR and building what you need from TPL is not easy. CCR and TPL are not symmetrical solutions. TPL is much more granular and general. CCR is tailored to solving coordination problems typically encountered in Robotics.

However, many of the TPL patterns fit somewhere inside of CCR. So, a logical way to do a TPL to CCR comparison is to replace a segment of CCR functionally with TPL code. Using some prototype sample code I developed to understand where TPL patterns fit within CCR, I'm going to walk through how I replaced a segment of CCR functionality with TPL code.

Constraints and Caveats

Before reviewing the code, there are some facts that I need to clarify.

First, I don't know CCR internals. The prototype mimics some of the CCR behavior, but I have no access to the CCR source code, so I don't know if the behavior is accurate. The sample focuses more on replacing functionality, but not on accurately replacing functionality. So, for example, performance may be better or worse with equivalent TPL functionality.

Also, the prototype is not CCR feature complete. I limited the scope to the Receiver Arbiter functionality. I did not review things like Choice, Interleave, and MultiplePortReceive Arbiters. Suspending and Creation CCR functionality was not part of the sample either. I also did nothing to handle exceptions.

This article does assume some familiarity with CCR. A complete introduction to CCR is beyond the scope of this article, but you'll find helpful resources at the end of the article.

Finally, the goal of this article was to look at where TPL fit into CCR and then, extrapolate from the conversion experience to determine whether I could replace CCR with TPL parts. This article is only a starting point for a developer's evaluation. There are no simple answers in this article.

With these facts in mind, I'll begin with an overview of the sample code.

Sample Overview

I took a sample from a prior article, Extending Microsoft's Concurrency and Coordination Runtime with MSMQ and replaced what the CCR was doing with an assembly built from TPL classes mimicking CCR functionality. Here is a summary of the major classes I replaced with equivalent TPL based classes:
  • Port - In CCR, the Port serves as a conduit into CCR. Port is a generic class tied to the class carrying the message payload into CCR. The message payload is a class containing the delegate function and accompanying data.
  • Arbiter - An Arbiter handles Port activation and dictates the coordination pattern with CCR. As I stated earlier, I limited the sample code to the Receiver Arbiter. Arbiters also tie DispatcherQueues to a Port.
  • Dispatcher - The Dispatcher pulls messages from DispatcherQueues , and executes the payload on a set of Threads allocated inside of the Dispatcher.

After creating the TPL based assembly I removed all reference to CCR and ran the sample using the TPL assembly. The execution flow mirrors that of CCR. The graphic below depicts execution.


Figure 1: TPL and CCR execution. Source: PDC 2008

I'll review each class in more detail starting with the Port class.

Port<T>

Below is the Port class implementation from the sample.

public class Port<T> 
{
    internal Handler<T> Handler { get; set; }
    internal DispatcherQueue Queue { get; set; }

    public void Post(T classRef)
    {
        var invoke = new InvokeT<T>(Handler, classRef);

        this.Queue.Enqueue(invoke);
    }


}

Most of the class functionality centers on packaging the delegate and accompanying data so other parts of the sample can execute the code. Like the CCR Port class, this implementation leverages generics.

Keeping with the CCR spirit, the public method "Post" initiates everything. Leveraging generics, Post is type safe. Internal functions hide code specific to the coordinating with the other classes, keeping the public interface clean.

IHandlerInvoker interface wraps execution and data together for consumption downstream. Most of the Port code does nothing with TPL. Like in CCR, this Port class works in conjunction with the Arbiter class.



.NET Framework 4.0 Task Parallell Library vs. the Concurrency and Coordination Runtime

Arbiter

Below is the sample Arbiter class implementation.

public static class Arbiter
{
    public static void Activate(DispatcherQueue queue, SetQueueReceiver receiver)
    {
        receiver.SetQueue(queue);
        queue.Resume();
    }

    public static Receiver<T> Receive<T>(bool persist, Port<T> port, Handler<T> handler)
    {
        port.Handler = handler;
        var rec = new Receiver<T> ();

        rec.Port = port;

        return rec;
    }
}

Like the Port I kept with the CCR spirit. Though, in the Arbiter, because much of the scope of the solution cut out what the Arbiter does, the implementation seems awkward (at best). Arbiter connects the Port to a DispatcherQueue, linking the Port to the classes performing the execution.

The really interesting part of the application is the Dispatcher and DispatcherQueue interaction.

DispatcherQueue and Dispatcher

Below are the primary parts of the DispatcherQueue and Dispatcher interaction.

public class DispatcherQueue
{
public string Name { get; private set; }
private Dispatcher _dispatcher = null;
private BlockingCollection<IHandlerInvoker> _queue = new BlockingCollection<IHandlerInvoker>();
private Task _task = null;

public DispatcherQueue(string name, Dispatcher dispatcher)
{
    this.Name = name;
    _dispatcher = dispatcher;

    _dispatcher.RegisterQueue(this);
}

public void Resume()
{
    _task = Task.Factory.StartNew(() =>
        {
            foreach (var invoker in _queue.GetConsumingEnumerable())
            {
                _dispatcher.Run(invoker);
            }
        }, TaskCreationOptions.LongRunning);
}

Most of DispatcherQueue functionality is handled in a BlockingCollection. As you can see the BlockingCollection sits in a "for loop" running in a LongRunning Task. IHandlerInvoker interface based classes are posted to the BlockingCollection from the Port class.

BlockingCollection handles all the locking and yielding required to make this code as simple as it appears.

A DispatcherQueue is associated with a Dispatcher. In the sample, the Dispatcher simply wraps the default TaskScheduler. TPL TaskScheduler and Dispatcher have similar duties. That is both classes collect the executing work and schedule the work to run on a pool of Threads. CCR Dispatcher schedules execution Round-Robin style. TPL default TaskScheduler is different, but a custom TaskScheduler can be constructed to work Round-Robin style.

A developer may even find a custom TaskScheduler in the TPL sample code.

TPL Samples

When putting the sample code together I stumbled on some useful code among the TPL samples shipping with the .NET Framework 4.0 SDK. Among the samples was a TaskScheduler working Round-Robin style along with a dozen other TaskSchedulers each for handling different styles of work.

Additionally, CCR has been described as a good platform for handling Async work. TPL is also a good platform for Async work. Among the samples you'll notice an AsnycCall class that may be a place to turn for wrapping Asnyc work.

You'll find links to more information on the samples in the sources at the end of the article.

Conclusion

Much of what CCR does can be expressed in TPL code. The sample code accompanying this article illustrates one way to compare the two solutions. Deciding between TPL and CCR comes down to determining how much of CCR a developer will really leverage in an application and how much debugging/development will be required to get equivalent CCR functionality from TPL. That includes whether there will be a significant performance difference between one of the solutions. Look to TPL samples for further guidance and inspiration.

Resources

Reason for Choosing LongRunning Task
TPL Sample Documentation
Introduction to CCR
CCR and MSMQ Original Source code

Related Article





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.

Comments

  • There are no comments yet. Be the first to comment!

Leave a Comment
  • Your email address will not be published. All fields are required.

Top White Papers and Webcasts

  • Live Event Date: November 20, 2014 @ 2:00 p.m. ET / 11:00 a.m. PT Are you wanting to target two or more platforms such as iOS, Android, and/or Windows? You are not alone. 90% of enterprises today are targeting two or more platforms. Attend this eSeminar to discover how mobile app developers can rely on one IDE to create applications across platforms and approaches (web, native, and/or hybrid), saving time, money, and effort and introducing apps to market faster. You'll learn the trade-offs for gaining long …

  • Live Event Date: October 29, 2014 @ 11:00 a.m. ET / 8:00 a.m. PT Are you interested in building a cognitive application using the power of IBM Watson? Need a platform that provides speed and ease for rapidly deploying this application? Join Chris Madison, Watson Solution Architect, as he walks through the process of building a Watson powered application on IBM Bluemix. Chris will talk about the new Watson Services just released on IBM bluemix, but more importantly he will do a step by step cognitive …

Most Popular Programming Stories

More for Developers

Latest Developer Headlines

RSS Feeds