Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

.NET Framework 4.0: Chaining tasks in a loop

I want to chain multiple Tasks, so that when one ends the next one starts. I know I can do this using ContinueWith. But what if I have a large number of tasks, so that:

t1 continues with t2

t2 continues with t3

t3 continues with t4

...

Is there a nice way to do it, other than creating this chain manually using a loop?

like image 928
Ilya Kogan Avatar asked Mar 30 '11 12:03

Ilya Kogan


2 Answers

Well, assuming you have some sort of enumerable of Action delegates or something you want to do, you can easily use LINQ to do the following:

// Create the base task.  Run synchronously.
var task = new Task(() => { });
task.RunSynchronously();

// Chain them all together.
var query = 
    // For each action
    from action in actions

    // Assign the task to the continuation and
    // return that.
    select (task = task.ContinueWith(action));

// Get the last task to wait on.
// Note that this cannot be changed to "Last"
// because the actions enumeration could have no
// elements, meaning that Last would throw.
// That means task can be null, so a check
// would have to be performed on it before
// waiting on it (unless you are assured that
// there are items in the action enumeration).
task = query.LastOrDefault();

The above code is really your loop, just in a fancier form. It does the same thing in that it takes the previous task (after primed with a dummy "noop" Task) and then adds a continuation in the form of ContinueWith (assigning the continuation to the current task in the process for the next iteration of the loop, which is performed when LastOrDefault is called).

like image 194
casperOne Avatar answered Oct 05 '22 22:10

casperOne


You may use static extensions ContinueWhenAll here.

So you can pass multiple tasks.


Update

You can use a chaining extension such as this:

public static class MyTaskExtensions
{
    public static Task BuildChain(this Task task, 
        IEnumerable<Action<Task>> actions)
    {
        if (!actions.Any())
            return task;
        else
        {
            Task continueWith = task.ContinueWith(actions.First());
            return continueWith.BuildChain(actions.Skip(1));
        }
    }
}
like image 30
Aliostad Avatar answered Oct 05 '22 22:10

Aliostad