What's the best way of achieving a parallel infinite Loop?
-
09-04-2021 - |
質問
I've gotten used to using Parallel.For() in .Net's parallel extensions as it's a simple way of parallelizing code without having to manually start and maintain threads (which can be fiddly). I'm now looking at an infinite loop (do something until I signal it to stop) that I wish to parallelize, there isn't an argument free Parallel.For() overload to do this so was wondering what the best approach here would be. In principle I could just do something like:
Parallel.For(0, int.Max)
But I'm suspecting that might not be an expected/efficient pattern for the work partitioning logic to handle(?)
Another option is something like:
for(;;)
{
Parallel.For(0, 128, delegate()
{
// Do stuff.
}
}
But that seems inelegant and may also result in inefficient work partitioning.
Right now my instinct is to do this manually by creating and maintaining my own threads, but I would be interested in getting some feedback/opinions on this. Thanks.
=== UPDATE ===
I'm using a simplified version of the code from the article in the accepted answer (I've removed the ParallelOptions parameter). Here's the code...
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;
}
}
An example usage would be:
Func<bool> whileCondFn = () => !_requestStopFlag;
ParallelUtils.While(whileCondFn, delegate()
{
// Do stuff.
});
解決
Stephen Toub has a post about Implementing Parallel While with Parallel.ForEach.
他のヒント
If you (really) want something infinite then you want it on as few cores a possible. None of the Parallel.For___
would be a good choice.
What you (probably) need is a separate Thread or a Task created with the LongRunning option.
And then make it wait on a semaphore, or as a last resort call Sleep() as often as possible.
Considering that it's infinit calculus request, but you need to have some finit state on every "cycle", I would say that I would change a solution with an external for(;;)
loop to execute a
Parallel.ForEach(...)
call on some event/state change. Like a Monitor
signal, event
notification, or something like that...