PFX Dec 2007 CTP: Executing Tasks Sequentially
An MSDN forum post from a couple of months ago (OK, so I am slow) asked if it was possible to schedule a task for execution after a previous task executed. Stephen Toub noted that handling the Completed event on a Task object would be the key to making such a design possible.
I have taken Stephen's design pattern and have implemented it in code. My fairly straightforward code sample is here in a ZIP file that contains a Visual Studio 2008 solution that illustrates the pattern. The driving force in the sample is in my implementation of a simple TaskCoordinator replacement that implements a new method called WaitAllSequential():
Post2674628.TaskCoordinator tc = new Post2674628.TaskCoordinator();
tc.WaitAllSequential(new Task[] { Task1, Task2, Task3 });
Unlike the static TaskCoordinator class that ships with the Dec 2007 CTP of the Parallel Extensions to the .NET Framework, my TaskCoordinator needs an object instance with which to work. I arrived at this conclusion after diving, for a bit, into extension methods. My original hope was to add a static extension method onto the existing TaskCoordinator class to handle the sequential task exection:
TaskCoordinator.WaitAllSequential(new Task[] { Task1, Task2, Task3 });
This is because C# (and, I presume, VB.NET) does not the authoring support static extension methods (this is discussed further in another MSDN forum post). This design would match nicely with the existing design of WaitAll():
TaskCoordinator.WaitAll(new Task[] { t1, t2, t3 });
But, without support for static extension methods, I'm left with requiring an instance. However, the TaskCoordinator class is an abstract class, so I can't write:
TaskCoordinator tc = new TaskCoordinator();
tc.WaitAllSequential(new Task[] { t1, t2, t3 });
Furthermore, I can't use a Task object, even though Task derives from TaskCoordinator:
TaskCoordinator tc = new Task();
tc.WaitAllSequential(new Task[] { t1, t2, t3 });
This is because the Task class does not have a parameterless constructor, and it seems like overkill to construct a valid Task object just to get all of this to work. Given all of this, then, the code design simply reverts to implementing a static class called TaskCoordinator in a different namespace.