简体   繁体   English

在while循环中实现Parallel.Foreach

[英]Implement Parallel.Foreach inside a while loop

I have scenario where I need to run a Parallel.Foreach within a while loop. 我有一个场景,我需要在while循环中运行Parallel.Foreach。 I need to understand the impact of this implementation in terms of how the processing will take place. 我需要了解这种实现在处理过程中的影响。 I will have an implementation something like this 我将有一个像这样的实现

 ConcurrentQueue<MyTable> queue = new ConcurrentQueue<MyTable>();

Here, I have initially added lot of items in queue but while execution also, more items can be added in the queue. 在这里,我最初在队列中添加了很多项目,但在执行时也可以在队列中添加更多项目。

while(true)
{
    Parallel.Foreach(queue, (myTable) => {some processing});
    Sleep(sometime);
}

Each time one item will be de-queued and new thread will be spawned to work with it, in the meanwhile new items will be added for that I need to keep an infinite while loop. 每次一个项目将被排队并生成新线程以使用它,同时将添加新项目,我需要保持无限循环。

Now, I need to understand that as concurrent queue is thread safe, I think each item will be processed one time only in spite of while above foreach but I am not sure about is that there will be multiple threads of foreach itself that will be spawning child threads or single copy of foreach will be running within while loop. 现在,我需要了解,因为并发队列是线程安全的,我认为每个项目只会被处理一次,尽管有时甚至超过foreach但我不确定是否会有多个foreach本身的线程将会产生子线程或foreach的单个副本将在while循环中运行。 I do not know how foreach itself is implemented. 我不知道foreach本身是如何实现的。

I have scenario where I need to run a Parallel.Foreach within a while loop. 我有一个场景,我需要在while循环中运行Parallel.Foreach。

I don't think you do. 我不认为你这样做。 You want to process new items as they come in in parallel, but I think this is not the best way to do that. 你想要并行处理新项目,但我认为这不是最好的方法。

I think the best way is to use ActionBlock from TPL Dataflow. 我认为最好的方法是使用TPL Dataflow的ActionBlock It won't waste CPU or threads when there are no items to process and if you set its MaxDegreeOfParallelism , it will process items in parallel: 当没有要处理的项目时,它不会浪费CPU或线程,如果您设置其MaxDegreeOfParallelism ,它将并行处理项目:

ActionBlock<MyTable> actionBlock = new ActionBlock<MyTable>(
    myTable => /* some processing */,
    new ExecutionDataflowBlockOptions
    {
        MaxDegreeOfParallelism = DataflowBlockOptions.Unbounded
    });


...

actionBlock.Post(someTable);

If you don't want to or can't (it's .Net 4.5 only) use TPL Dataflow, another option would be use a single Parallel.Foreach() (no while ) together with BlockingCollection and GetConsumingPartitioner() ( not GetConsumingEnumerable() !). 如果您不想或不能(仅限.Net 4.5)使用TPL Dataflow,另一个选项是使用单个Parallel.Foreach() (不会while )和BlockingCollection以及GetConsumingPartitioner()不是 GetConsumingEnumerable() !)。

Using this, the Parallel.Foreach() threads will be blocked when there are no items to process, but there also won't be any delays in processing (like the ones caused by your Sleep() ): 使用它时,如果没有要处理的项目,则会阻止Parallel.Foreach()线程,但处理中也不会有任何延迟(如Sleep()引起的延迟):

BlockingCollection<MyTable> queue = new BlockingCollection<MyTable>();

...

Parallel.ForEach(
    queue.GetConsumingPartitioner(), myTable => /* some processing */);

...

queue.Add(someTable);

I think each item will be processed one time only in spite of while above foreach but I am not sure 我认为每件物品都会被处理一次,尽管有时甚至超过了foreach,但我不确定

That's one reason why you should use one of the options above, since they mean you don't need to know much about the details of how they work, they just work. 这就是为什么你应该使用上面的一个选项的一个原因,因为它们意味着你不需要了解它们如何工作的细节,它们只是起作用。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM