我有一个场景,我需要在while循环中运行Parallel.Foreach。我需要了解这种实现在处理过程中的影响。我将有一个像这样的实现
ConcurrentQueue<MyTable> queue = new ConcurrentQueue<MyTable>();
在这里,我最初在队列中添加了很多项目,但在执行时也可以在队列中添加更多项目。
while(true)
{
Parallel.Foreach(queue, (myTable) => {some processing});
Sleep(sometime);
}
每次一个项目将被排队并且将生成新线程以使用它,同时将添加新项目,我需要保持无限循环。
现在,我需要明白,由于并发队列是线程安全的,我认为每个项目只会被处理一次,尽管有时甚至超过foreach但我不确定是否会有多个foreach本身的线程将生成子线程或foreach的单个副本将在while循环中运行。我不知道foreach本身是如何实现的。
答案 0 :(得分:3)
我有一个场景,我需要在while循环中运行Parallel.Foreach。
我不认为你这样做。您想要并行处理新项目,但我认为这不是最好的方法。
我认为最好的方法是使用TPL Dataflow中的ActionBlock
。当没有要处理的项目时,它不会浪费CPU或线程,如果设置了MaxDegreeOfParallelism
,它将并行处理项目:
ActionBlock<MyTable> actionBlock = new ActionBlock<MyTable>(
myTable => /* some processing */,
new ExecutionDataflowBlockOptions
{
MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
});
...
actionBlock.Post(someTable);
如果您不想或不能(仅限.Net 4.5)使用TPL数据流,则另一种选择是使用单Parallel.Foreach()
(无{{1 }}}与BlockingCollection
和GetConsumingPartitioner()
一起(不 while
!)。
使用此功能时,如果没有要处理的项目,GetConsumingEnumerable()
主题会被阻止,但也不会有任何处理延迟(例如由Parallel.Foreach()
引起的延迟) :
Sleep()
我认为每件物品都会被处理一次,尽管有时甚至超过了foreach,但我不确定
这就是为什么你应该使用上述选项之一的一个原因,因为它们意味着你不需要了解它们如何工作的细节,它们只是起作用。