【发布时间】:2014-09-03 12:07:09
【问题描述】:
我写了一个软件来处理图像并减少处理时间,我尝试使用多线程。下面是相关的sn-p。
bool Multithread = CheckMultithread();
UpdateParameters();
if (Multithread)
{
Parallel.For(0, FileNames.Length ,i => Solve(FileNames[i]));
}
else
{
foreach (string s in FileNames)
{
Solve(s);
}
}
这是我第一次尝试用 C# 编写多线程代码;但我相信不存在线程问题,因为处理一张图像不会干扰另一张图像的处理。
问题是:如果Multithread 是true,当处理 200 幅图像时,我会得到一个OutOfMemoryException...我想这种并行实现消耗的内存是顺序等效的 N 倍,其中N 是线程数。
我在单个类中使用非托管代码,但每次使用此类时,它都在 using 上下文中。作为参考,这个类是System.Drawing.Bitmap 的包装器。
每个线程消耗 +/- 400 MB 的内存,当抛出 OutOfMemoryException 时,程序正在使用大约 1300 MB 的内存。即使我有超过 9 GB 的可用内存。
我在Solve 方法中编写了以下解决方法代码。除了这个例外,我在 Solve() 的请求中添加了以下代码
if (GC.GetTotalMemory(false) > 1000*1000*1000)
{
lock (Manager.dasLock)
{
Manager.sw.Start();
GC.Collect();
Manager.sw.Stop();
}
}
通过解决方法,该软件能够处理所有 2000 多张图像而不会耗尽内存,但我的同行抱怨我不应该碰 GC。 那么,如何在不手动调用 GC 的情况下解决此问题?
【问题讨论】:
-
您是否尝试过保存处理后的图像并在保存后手动处理它们?并且 1,3gb RAM 上限是因为 32 位;)
-
您认为 Parallel.For 为每次迭代创建一个线程的假设是不正确的。它将集合划分为几个组,每个组在一个线程中运行。
-
只是为了确定,因为我发现您的最后几段令人困惑:如果您调用
GC.Collect它会导致OutOfMemoryException但没有它即使使用Parallel.For循环也一切正常? -
这是 32 位应用程序吗?如果是这样,无论您有多少 RAM,您都只有 2 GB 地址空间。将其设为 64 位进程,您的地址空间会增长很多。
-
可能相关的相关问题:Parallel.ForEach can cause a “Out Of Memory” exception if working with a enumerable with a large object(但不一定是重复的)。如果您设置最大并行度或创建一个采用较小块的自定义实践者,问题会消失吗?
标签: c# garbage-collection out-of-memory task-parallel-library