LockBits()抛出'内存溢出'在并行Foreach中
本文关键字:并行 Foreach 溢出 内存 LockBits 抛出 | 更新日期: 2023-09-27 18:13:56
我是c#和并行处理的新手。我正在尝试处理一堆图像,我已经写了处理方法。我已经在imagelist上添加了Parallel foreach循环,如下所示
Parallel.ForEach(Directory.GetFiles(path), new ParallelOptions { MaxDegreeOfParallelism = 2 }, fileName =>
{
List<string> tempList = new List<string>();
using (Bitmap imageBitmap= new Bitmap(fileName))
{
using (ImageProcessor imageProcessor= new ImageProcessor ())
{
tempList = imageProcessor.ProcessImage(imageBitmap);
}
}
if (tempList.Count != 0)
allElements.Add(tempList.FirstOrDefault());
});
在其中一种方法中,我使用LockBits
方法获得图像的BitMapData
并将该数据复制到byte[]
,但方法抛出异常,方法的代码为
private byte[] ImageToByteArray(Bitmap b, out int stride)
{
object sync = new object();
BitmapData bd;
lock (sync)
{
Rectangle rect = new Rectangle(0, 0, b.Width, b.Height);
bd = b.LockBits(rect, ImageLockMode.ReadOnly, PixelFormat.Format24bppRgb);//This line throwing the exception.
try
{
byte[] pxl = new byte[bd.Stride * b.Height];
Marshal.Copy(bd.Scan0, pxl, 0, bd.Stride * b.Height);
stride = bd.Stride;
return pxl;
}
finally
{
b.UnlockBits(bd);
}
}
}
我试图lock
使用LockBits
方法的代码,所以一次只有一个线程使用代码,因此内存。
我还尝试使用lock
调用父方法的方法,如
public List<string> ProcessImage(BitMap image)
{
object sync = new object();
int stride;
byte[] rawImg;
using (image)
{
lock (sync)
{
rawImg = ImageToByteArray(image, out stride);
}
processingImg = new ProcessImage(rawImg, image.Width, image.Height);
}
}
但是异常仍然存在。异常没有给我任何堆栈跟踪或解释,只有我得到的异常消息是Out Of Memory
。
我遇到了这个答案,当我减少MaximumDegreeOfParallelism
它工作正常。
所以基本上我想知道,1)为什么代码抛出Out Of Memory
异常超过2个线程,即使有lock
上的代码?2)如果我增加DegreeOfParallelism
,是否有可能避免这种例外?如果有任何帮助就太好了。
-
问题是你想处理的图像有多大。也许它们太大了。我的经验还表明,调用LockBits会分配额外的内存量——有效地将分配的内存量加倍。你有没有试着处理一些很小的照片?
-
代码中的锁什么都不做,因为你锁定了一个局部变量。如果你想在线程之间同步对临界区的访问,并且你想用锁来实现,那么你必须使用一个在所有这些线程之间共享的对象。在你的例子中,sync对象应该被声明为ImageProcessor类的私有字段。
-
我认为增加DegreeOfParallelism不会有任何帮助会使事情变得更糟,因为你的代码将需要更多的内存