Parallel.ForEach不旋转了新主题 [英] Parallel.ForEach not spinning up new threads

查看:102
本文介绍了Parallel.ForEach不旋转了新主题的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Parallel.ForEach不转了新的主题

Parallel.ForEach Not Spinning Up New Threads

大家好,我们有一个非常IO密集型的操作,我们编写了使用Parallel.ForEach从微软的并行扩展为.NET Framework。我们需要删除大量文件,我们重新present的文件被删除列表清单。每个嵌套的列表中有1000条消息在里面,我们有50个这样的名单。这里的问题是,当我看到在日志中之后,我只看到我们的Parallel.ForEach块内的一个线程执行。

Hello all, we have a very IO-intensive operation that we wrote using Parallel.ForEach from Microsoft's Parallel Extensions for the .NET Framework. We need to delete a large number of files, and we represent the files to be deleted as a list of lists. Each nested list has 1000 messages in it, and we have 50 of these lists. The issue here is that when I look in the logs afterwards, I only see one thread executing inside of our Parallel.ForEach block.

下面就是code是这样的:

Here's what the code looks like:

List<List<Message>> expiredMessagesLists = GetNestedListOfMessages();
foreach (List<Message> subList in expiredMessagesLists)
{
    Parallel.ForEach(subList, msg =>
    {
        try
        {
            Logger.LogEvent(TraceEventType.Information, "Purging Message {0} on Thread {1}", msg.MessageID, msg.ExtensionID, Thread.CurrentThread.Name);

            DeleteMessageFiles(msg);
        }
        catch (Exception ex)
        {
            Logger.LogException(TraceEventType.Error, ex);
        }
    });
}

我写了一些样品code具有简单的数据结构,并没有IO逻辑,我可以看到Parallel.ForEach块内执行多​​个不同线程。我们正在做的code以上不正确的东西用Parallel.ForEach?难道是列出了多数民众赞成绊倒它的列表,或者是有某种线程限制为IO操作?

I wrote some sample code with a simpler data structure and no IO logic, and I could see several different threads executing within the Parallel.ForEach block. Are we doing something incorrect with Parallel.ForEach in the code above? Could it be the list of lists that's tripping it up, or is there some sort of threading limitation for IO operations?

推荐答案

有几种可能性。

首先,在大多数情况下, Parallel.ForEach 不会产生一个新的线程。它使用了.NET 4线程池(所有TPL的一样),并会重用线程池线程。

First off, in most cases, Parallel.ForEach will not spawn a new thread. It uses the .NET 4 ThreadPool (all of the TPL does), and will reuse ThreadPool threads.

话虽这么说,Parallel.ForEach使用基于列表的大小的分区策略传递给它。我的第一个猜测是,你的外列表中有很多消息,但内部列表只有一个Message实例,所以给ForEach分区只使用一个线程。随着一个元素,并行是足够聪明,只使用主线程,而不是旋转的工作到后台线程。

That being said, Parallel.ForEach uses a partitioning strategy based on the size of the List being passed to it. My first guess is that your "outer" list has many messages, but the inner list only has one Message instance, so the ForEach partitioner is only using a single thread. With one element, Parallel is smart enough to just use the main thread, and not spin work onto a background thread.

通常情况下,在这样的情况下,最好是并行的外循环,而不是内部循环。这通常会带来更好的性能(因为你有更大的工作项),尽管它很难知道,无需环路尺寸的良好意识以及工作单元的大小。你也可以,潜在的,并行的内环和外环两个,但没有分析,这将会是很难说什么会是最好的选择。

Normally, in situations like this, it's better to parallelize the outer loop, not the inner loop. That will usually give you better performance (since you'll have larger work items), although it's difficult to know without having a good sense of the loop sizes plus the size of the Unit of Work. You could also, potentially, parallelize both the inner and outer loops, but without profiling, it'd be difficult to tell what would be the best option.

另外一个可能性:

尝试使用 [Thread.ManagedThreadId] [1] ,而不是Thread.CurrentThread.Name为您记录。由于并行使用线程池线程,名称往往是在多个线程相同。你可能会认为你只使用一个线程,当你在实际上使用一个以上的....

Try using [Thread.ManagedThreadId][1] instead of Thread.CurrentThread.Name for your logging. Since Parallel uses ThreadPool threads, the "Name" is often identical across multiple threads. You may think you're only using a single thread, when you're in fact using more than one....

这篇关于Parallel.ForEach不旋转了新主题的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆