Библиотека параллельных задач. Вложенная задача не запускается

Я работаю с новой библиотекой TPL .NET и столкнулся с каким-то странным для меня поведением, которое я не могу объяснить. В моем случае почему-то не запускается вложенная задача. Я упростил решение до следующего:

        bool flag = false;

        for (int i = 0; i < 5; i++)
        {
            Task.Factory.StartNew(() =>
                         {
                            while (true) // a lot of newcoming tasks
                            {
                                Thread.Sleep(200); //do some work
                                Task.Factory.StartNew(() =>
                                             {
                                                 flag = true;
                                              });
                            }
                         });
        }

        Thread.Sleep(2000);
        Assert.IsTrue(flag);

У меня есть 5 задач, которые работают одновременно. Каждая задача извлекает некоторые элементы из ожидающей очереди, выполняет некоторую операцию, а затем пытается запустить вложенную задачу для результатов этой операции. Проблема в том, что если элементов слишком много (while (true) имитирует это) и все 5 задач постоянно выполняются, вложенные задачи не запускаются. Может быть запущен только после того, как большинство задач с циклом while завершат свое выполнение.

Кажется, что-то не так с операторами while, которые блокируют выполнение вложенных задач, но я не знаю что :)


person lostaman    schedule 28.07.2010    source источник


Ответы (2)


Task.Factory.StartNew не запускает задачу, она добавляет задачу в список задач, которые должны быть запланированы, и планировщик может решить, когда запускать задачу на основе таких вещей, как; количество доступных ядер (размер пула потоков), текущая загрузка ЦП и пропускная способность существующей работы.

Вам следует прочитать раздел о планировании задач здесь:

http://parallelpatterns.codeplex.com/releases/view/48562

Страница 63 PDF-файла и далее.

Параметр LongRunning «устраняет» вашу проблему, полностью обходя пул потоков. У этого есть некоторые недостатки, так как это позволит вам создать больше потоков, чем ваша система действительно должна использовать, это снизит производительность, вызывая чрезмерное переключение контекста.

Такие эксперименты, как приведенный выше код с использованием спящего режима потока, вводят в заблуждение, потому что они «обманывают» планировщик. Он видит, что он добавил больше работы, но при этом нагрузка на ЦП не увеличилась.63 Вы должны заменить спящий режим на жесткий цикл, который содержит математику (например, вычисление Sqrt (), например.

Почему бы просто не создать единственный внешний цикл, который считывает элементы из очереди и выполняет их в Задаче. Таким образом, ваше приложение будет максимально использовать доступный параллелизм системы, не перегружая ее.

Возможно, стоит взглянуть на следующий ответ:

Библиотека параллельных задач WaitAny Design

person Ade Miller    schedule 30.07.2010

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

Вы ведь не говорите, что вложенные задачи не запускаются, не так ли? Вы просто говорите, что они не начинают работать с того момента, который вам хотелось бы, а начинают позже.

person Will Dean    schedule 28.07.2010
comment
да. Они запускаются позже, но я хочу, чтобы они запускались параллельно с выполнением задач. Если я изменю ограничение для индекса «i» в цикле, например, на 10, у меня будет создано и запущено 10 потоков. Но ни одна вложенная задача не будет выполняться параллельно этим задачам. - person lostaman; 28.07.2010
comment
Добавление TaskCreationOptions.LongRunning для родительских задач решило проблему. - person lostaman; 28.07.2010
comment
Это решает проблему в примере ниже, но не в моем проекте :( - person lostaman; 28.07.2010