Каков наилучший способ достижения параллельного бесконечного цикла? - PullRequest
9 голосов
/ 29 декабря 2011

Я привык использовать Parallel.For () в параллельных расширениях .Net, поскольку это простой способ распараллеливания кода без необходимости вручную запускать и поддерживать потоки (что может быть сложным). Сейчас я смотрю на бесконечный цикл (делайте что-то, пока я не сообщу об этом, чтобы остановить), который я хочу распараллелить, нет перегрузки без параллелизма Parallel.For (), чтобы сделать это, поэтому мне было интересно, какой лучший подход здесь будет быть. В принципе я мог бы просто сделать что-то вроде:

Parallel.For(0, int.Max)

Но я подозреваю, что это может быть не ожидаемый / эффективный шаблон для обработки логики разбиения работы (?)

Другой вариант - что-то вроде:

for(;;)
{
    Parallel.For(0, 128, delegate()
    {
       // Do stuff.
    }
}

Но это кажется не элегантным и может также привести к неэффективному разделению работы.

Прямо сейчас мой инстинкт состоит в том, чтобы делать это вручную, создавая и поддерживая мои собственные темы, но мне было бы интересно получить некоторые отзывы / мнения по этому вопросу. Спасибо.

=== ОБНОВЛЕНИЕ ===

Я использую упрощенную версию кода из статьи в принятом ответе (я удалил параметр ParallelOptions). Вот код ...

public class ParallelUtils
{
    public static void While(Func<bool> condition, Action body) 
    { 
        Parallel.ForEach(IterateUntilFalse(condition), ignored => body()); 
    }

    private static IEnumerable<bool> IterateUntilFalse(Func<bool> condition) 
    { 
        while (condition()) yield return true; 
    }
}

Пример использования:

Func<bool> whileCondFn = () => !_requestStopFlag;
ParallelUtils.While(whileCondFn, delegate()
{
    // Do stuff.


});

Ответы [ 3 ]

8 голосов
/ 29 декабря 2011
2 голосов
/ 29 декабря 2011

Если вы (действительно) хотите что-то бесконечное, то вы хотите, чтобы это было как можно меньше ядер.Ни один из Parallel.For___ не будет хорошим выбором.

Что вам (вероятно) нужно, это отдельный поток или задача, созданная с помощью параметра LongRunning.

А затем заставьте его ждать на семафоре или, в крайнем случае, вызывайте Sleep () как можно чаще.

1 голос
/ 29 декабря 2011

Учитывая, что это запрос на бесконечное исчисление, но вам нужно иметь какое-то конечное состояние в каждом "цикле", я бы сказал, что я бы изменил решение с помощью внешнего цикла for(;;), чтобы выполнить Parallel.ForEach(...) вызов при изменении какого-либо события / состояния. Как сигнал Monitor, уведомление event или что-то в этом роде ...

...