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()抛出'内存溢出'在并行Foreach中

  1. 问题是你想处理的图像有多大。也许它们太大了。我的经验还表明,调用LockBits会分配额外的内存量——有效地将分配的内存量加倍。你有没有试着处理一些很小的照片?

  2. 代码中的什么都不做,因为你锁定了一个局部变量。如果你想在线程之间同步对临界区的访问,并且你想用来实现,那么你必须使用一个在所有这些线程之间共享的对象。在你的例子中,sync对象应该被声明为ImageProcessor类的私有字段。

  3. 我认为增加DegreeOfParallelism不会有任何帮助会使事情变得更糟,因为你的代码将需要更多的内存