简体   繁体   中英

LockBits() Throwing 'Out Of Memory' in Parallel Foreach?

Iam new to the c# and Parallel processing. I am trying to process the bunch of images and i have written methods for processing.And I have added the Parallel foreach loop on imagelist as below

    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());
            });

In one of the method I have used the LockBits method to get the BitMapData of the image and copying that data to the byte[] but method is throwing the exception the code of method is

   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);
            }
        }
    }

I tried to lock the code which is using the LockBits method so at a time only one thread at a time use the code and hence the memory.

I also tried using the lock with call of the methods from parent method like

    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);
        }
  }

but still the exception is there. The exception isn't give me any stack trace or explanation only Exception message I am getting is Out Of Memory .

I came across this answer and when i reduced the MaximumDegreeOfParallelism it worked correctly.

So basically I wanted to know, 1) why the code was throwing the Out Of Memory exception for more that 2 threads even there is lock on the code? 2) And is it possible to avoid this exception if I increase the DegreeOfParallelism ? Any help would be great.


In case of any confusion feel free to comment.

  1. The question is how big are images that you want to process. Maybe they are just too big. My experience also shows that calling LockBits allocates additional amount of memory - effectively it doubles amount of allocated memory. Did you try to process some very small picture?

  2. The lock in your code does nothing because you are locking on a local variables. If you want to synchronize access to a critical section between threads and you want to do so with lock then you have to use an object that is shared between all these threads. In your case sync object should be declared as a private field of ImageProcessor class.

  3. I think that increasing DegreeOfParallelism will not help or even will make things worse because your code will need more memory to process more images.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM