jgeurts/FluentScheduler — pull request #23 by alexdancho (2013-07-26 18:09:04+00:00)
Title: Adds support for running multiple tasks in a single schedule

The main idea behind this pull request is to allow for grouping of tasks into a single schedule. We have a few use cases in our application that require tasks to fire sequentially, especially when it involves manipulating persisted data. We still wanted to keep those functions as atomic as possible, so grouping them into one large instantiated implementation of ITask wasn't feasible. This pull request adds the capability for "chaining" tasks together when adding a Schedule to a Registry:

```csharp
public MyRegistry()
{
//Schedule multiple tasks to be run in a single schedule
Schedule().AndThen().ToRunNow().AndEvery(5).Minutes();
}
```

I also added in a Concurrent() function to Schedule to indicate that multiple tasks in a schedule can be run in parallel rather than sequentially:

```csharp
public MyRegistry()
{
//Schedule multiple tasks to be run in a single schedule
Schedule().AndThen().Concurrently().ToRunNow().AndEvery(5).Minutes();
}
```

It also works with simple and complex actions as well:

```csharp
public MyRegistry()
{
//Schedule multiple tasks to be run in a single schedule
Schedule(() =>
{
Console.WriteLine("First task will fire first!");
Console.WriteLine("Waiting four seconds...");
Thread.Sleep(4000);
}).AndThen(() =>
{
Console.WriteLine("Then the second task fires!");
}).WithName("Multitask").ToRunNow();
}
```

This required moving the ITask activator function out into its own class (which I named ITaskFactory, though that name could stand to be thought about for awhile more and probably revisited), which means this *is* a breaking change, as it requires anyone using a dependency injector to add a new class that extends ITaskFactory and override the GetTaskInstance function there, rather than directly on their registry class. However, I think this is a logical choice that mirrors other similar applications. If there's a way to avoid adding that additional class, I'd be all ears.

I did add a function onto TaskManager to set it into testing mode, in which it adds a Task.Wait() to the main task function. This was in order to run some asserts that the Execute delegates are actually being called. I'm not so sure this is necessary, but I also didn't necessarily see the harm.

Not much in core functionality has changed beyond that - anything that was done before should be perfectly compatible with this pull request.