Использование TPL для выполнения некоторых «заданий» - PullRequest
0 голосов
/ 15 апреля 2011

Я запускаю небольшой «менеджер заданий», он выполняет некоторый объект «Задание», реализующий метод «IJob».Каждый IJob завершается возвратом потенциального списка новых заданий.

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

Я ищу, как распараллелить это с TPL.

У меня есть несколько идей, но ни одна из них не действительна из-за моих ограничений:

  • Мне нужно ограничить количество потоков (скажем, до 4), потому что некоторые запросы запрашивают веб-сайт, который не допускает более 4 одновременных запросов (я думаю, что я могу управлять этим с помощью семафора)
  • Мой список заданий изменится, поэтому я просто не могу запустить 4 потока, разделить количество заданий на число потоков, и каждый поток запускает свой стек заданий.
  • Может быть, иногда, если я 'В 4-м потоке у меня есть только одно задание, но я не могу остановить другой поток, потому что, возможно, последнее задание, которое я запущу, создаст много новых заданий.

Спасибовам очень нравится!

Ответы [ 3 ]

0 голосов
/ 16 апреля 2011

Ознакомьтесь с параллельным программированием в Microsoft .NET от Кэмпбелла, Джонсона, Миллера и Тауба ... в частности, в главе 3 «Глобальная очередь с локальными потоками рабочих очередей через TPL, в которых используется алгоритм кражи работы» для балансировки нагрузки.

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

0 голосов
/ 26 марта 2012

Это действительно динамический параллелизм задач.Ваш код перебирает все ваши задания и выполняет каждое из них.Каждое задание может добавлять новые задания в использование addMethod и параллельной очереди.

public static void ParallelWhileNotEmpty<T>(
  IEnumerable<T> initialValues, 
  Action<T, Action<T>> body)
{
  var opts = new ParallelOptions { MaxDegreeOfParallelism = 10 };
  var from = new ConcurrentQueue<T>(initialValues);  
  while (!from.IsEmpty)
  { 
    var to = new ConcurrentQueue<T>();
    Action<T> addMethod = to.Enqueue; 
    Parallel.ForEach(from, opts. body(v, addMethod));        
    from = to;
  }
}

Таким образом, «цикл» открыт и заканчивается, пока не закончится работа.Очевидно, что ваше реальное приложение будет учитывать дублирующиеся URL-адреса, а не добавлять их и т. Д. Но это позволяет вашему приложению динамически добавлять работу.Вы можете использовать ParallelOptions для ограничения параллелизма или написать планировщик.

Для получения дополнительной информации о параллелизме динамических задач см.

http://msdn.microsoft.com/en-us/library/ff963551.aspx

.код для примера см.

http://parallelpatterns.codeplex.com/SourceControl/changeset/view/54510#795590

Оба из вышеупомянутых обсуждают другие альтернативные варианты этой темы.

Если вы хотите, чтобы пользовательский планировщик ограничивал степень параллелизмасм. пример на MSDN

http://msdn.microsoft.com/en-us/library/ee789351.aspx

0 голосов
/ 15 апреля 2011

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

Рид Копси имеет пример в своем блоге.

...