Библиотека параллельных задач - узнайте, когда все задачи завершены - PullRequest
5 голосов
/ 26 февраля 2012

Я использую Task Parallel Library для запуска некоторых задач, например так:

    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();
    }

Проблема в том, что некоторые задачи сами могут создавать новые задачи. Вот как выглядит WorkerClass:

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);
    }
}

Для каждого значения i, кратного 3, запускается новая задача.

Я бы хотел иметь возможность дождаться завершения всех задач (включая те, которые были созданы другими задачами).

Есть ли чистый / встроенный способ сделать это (с TPL или без него)?

1 Ответ

15 голосов
/ 26 февраля 2012

Сохраните ссылку на все задачи верхнего уровня, а затем просто используйте 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 );

Что касается дочерних задач, просто убедитесь, что вы прикрепили их к родительской задаче. Это означает, что родительская задача не перейдет в завершенное состояние, пока все дочерние задачи также не будут завершены.

    Task.Factory.StartNew(() => { }, TaskCreationOptions.AttachedToParent);
...