【发布时间】:2009-12-07 17:33:52
【问题描述】:
Parallel.ForEach 没有启动新线程
大家好,我们有一个非常 IO 密集型操作,我们使用 Microsoft 的 .NET Framework 并行扩展中的 Parallel.ForEach 编写。我们需要删除大量文件,我们将要删除的文件表示为列表的列表。每个嵌套列表中有 1000 条消息,我们有 50 个这样的列表。这里的问题是,当我之后查看日志时,我只看到一个线程在我们的 Parallel.ForEach 块内执行。
代码如下:
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);
}
});
}
我用更简单的数据结构和没有 IO 逻辑编写了一些示例代码,我可以看到在 Parallel.ForEach 块中执行了几个不同的线程。我们在上面的代码中对 Parallel.ForEach 做了什么不正确的事情吗?可能是列表列表导致了问题,还是 IO 操作存在某种线程限制?
【问题讨论】:
-
并行删除文件能获得多少收益?数额很大吗?您的底层硬件配置是否支持这样的收益?
-
DeleteMessageFiles的代码是什么 -
如果您使用 Thread.ManagedThreadId 而不是 Thread.CurrentThread.Name,您会得到相同的结果吗?对于线程池线程,名称通常看起来相同,即使它们不是......
-
@roygbiv:这很好,如果“删除文件”是本地删除。如果以多线程方式完成,磁盘 IO 可能会更慢。在不知道“DeleteMessageFiles”做什么的情况下,很难说清楚。它可能会做其他大量的“工作”,在这种情况下,这将是一个很好的并发机会。
-
@roygbiv 我还不能说我们通过并行删除获得了多少,因为我们还没有成功地做到这一点。我上面发布的代码需要从网络存储中删除几百万个文件,所以这里有很多阻塞。在硬件配置方面,我只能推测我们的硬件会支持这样的增益,因为这是一个重型NAS。
标签: c# .net multithreading parallel-extensions