Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Task Parallel Library - Know when all tasks are finished

I use Task Parallel Library to start some tasks, like so:

    public static void Main()
    {
        for (var i = 0; i < 10; i++)
        {
            var x = i;
            Task.Factory.StartNew(() => new WorkerClass(x).Do());
        }

        // (*) Here I'd like to wait for all tasks to finish
        Task.WaitAll(); 

        Console.WriteLine("Ready.");
        Console.ReadLine();
    }

The problem is that some tasks can create new tasks themselves. This is how WorkerClass looks like:

public class WorkerClass
{
    private static readonly NLog.Logger Log = NLog.LogManager.GetCurrentClassLogger();

    private readonly int _i;

    public WorkerClass(int i)
    {
        _i = i;
    }

    public void Do()
    {
        if (_i % 3 == 0)
            Task.Factory.StartNew(() => new WorkerClass(_i + 101).Do());

        Log.Info("Started {0}", _i);
        Thread.Sleep(2000);
        Log.Info("Done {0}", _i);
    }
}

For every value of i that's a multiple of 3, a new Task is started.

I'd like to be able to wait until all tasks (including the ones created by other tasks) are finished.

Is there a clean/built-in way to do this (with or without TPL)?

like image 827
Cristian Lupascu Avatar asked Feb 26 '12 08:02

Cristian Lupascu


People also ask

Does parallel foreach wait for completion?

You don't have to do anything special, Parallel. Foreach() will wait until all its branched tasks are complete. From the calling thread you can treat it as a single synchronous statement and for instance wrap it inside a try/catch.

Is task WhenAll parallel?

WhenAll() method in . NET Core. This will upload the first file, then the next file. There is no parallelism here, as the “async Task” does not automatically make something run in in parallel.

Why are tasks better than threads?

It is always advised to use tasks instead of thread as it is created on the thread pool which has already system created threads to improve the performance. The task can return a result. There is no direct mechanism to return the result from a thread. Task supports cancellation through the use of cancellation tokens.


1 Answers

Keep a reference to all top-level tasks and then just use WaitAll:

    var tasks = new Task[10];
    for (var i = 0; i < 10; i++)
    {
        var x = i;
        tasks[i] = Task.Factory.StartNew(() => new WorkerClass(x).Do());
    }

    Task.WaitAll( tasks );

As for the child tasks, just make sure you attach them to the parent task. This means that the parent task will not go into a complete state until all child tasks are also finished.

    Task.Factory.StartNew(() => { }, TaskCreationOptions.AttachedToParent);
like image 185
Tyson Avatar answered Oct 05 '22 09:10

Tyson