Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Wait for dynamically created Tasks until they completed

My program is creating some Tasks to do some work. Now I want to wait for all tasks to complete before I will exit my program.

I know the Task.WaitAll(...) method but in my case I want to create some Tasks dynamically --> they don't exist when Task.WaitAll() is called.

My question now is: how can I wait for all running Tasks until they are completed?

This is what I'm doing now.

It works but I want to be sure this is also a good way to do it.

public class Test
{
    public ConcurrentBag<Task> RunningTasks { get; set; } 

    public Test()
    {
        RunningTasks = new ConcurrentBag<Task>();
    }

    public void RunIt(){

        //...create some Tasks asynchronously so they may be created in a few seconds and add them to the list like
        //RunningTasks.Add(...);


        //Just wait until all tasks finished.
        var waitTask = Task.Run(() =>
        {
            while (true)
            {
                if (RunningTasks.All(t => t.IsCompleted))
                    break;

                Thread.Sleep(1000);
            }
        });

        waitTask.Wait();

    }
}
like image 989
Tobias Koller Avatar asked Mar 28 '16 14:03

Tobias Koller


1 Answers

Task.WhenAll() will take an array of Task, and the ConcurrentBag<T> supports the ToArray() extension method, so you can simply do:

await Task.WhenAll(RunningTasks.ToArray())

or if you don't want to use the await keyword:

Task.WhenAll(RunningTasks.ToArray()).Wait()

UPDATE

So if your RunningTasks is changing after the initial call you can do this pretty easily to handle it:

while(RunningTasks.Any(t=>!t.IsCompleted))
{
    Task.WhenAll(RunningTasks.ToArray());
}

The main benefit over your method is that this will yield the thread to other work while it waits, where your code will tie up the thread in a sleep state until all the tasks are completed.

like image 109
CodingGorilla Avatar answered Oct 25 '22 01:10

CodingGorilla