0

I am trying to parallelize an operation on an image using the code below , but I get an One or more errors occurred error.

Looking into the inner exception I can see the error {"Object is currently in use elsewhere."} has occurred.

Note: CoverImage and SecretImage are Bitmaps

 Parallel.For(0, CoverImage.Width, x =>
            {
                for (int y = 0; y < CoverImage.Height; y++, SecretImageHeight++)
                {
                    Color coverImagesPixel = CoverImage.GetPixel(x, y);
                    Color secretImagesPixel = SecretImage.GetPixel(SecretImageWidth, SecretImageHeight);

                    int r = (coverImagesPixel.R & coverImageMask) + ((secretImagesPixel.R >> shift) & secretImageMask);
                    int g = (coverImagesPixel.G & coverImageMask) + ((secretImagesPixel.G >> shift) & secretImageMask);
                    int b = (coverImagesPixel.B & coverImageMask) + ((secretImagesPixel.B >> shift) & secretImageMask);

                    StegoImage.SetPixel(x, y, Color.FromArgb(255, r, g, b));
                }
                SecretImageHeight = 0;
                SecretImageWidth++;
            }
            );

I tried using a mutex like this :

mutex.WaitOne();
StegoImage.SetPixel(x, y, Color.FromArgb(255, r, g, b));
mutex.ReleaseMutex();

But still to no avail (I get the same error).

halfer
  • 19,824
  • 17
  • 99
  • 186
Hossein
  • 24,202
  • 35
  • 119
  • 224
  • What types are CoverImage and SecretImage? Are they in use in the application elsewhere? What happens when you wrap access to them in the mutex - they might be causing the problem as well. – thorkia Jun 18 '15 at 14:08
  • 1
    If you follow the exception, which line causes it? I'm guessing either `SecretImage` or `CoverImage` is not thread-safe. – flindeberg Jun 18 '15 at 14:09
  • @thorkia:They are of type Bitmap. @ Flindeberg: It just highlights the Parallel.For block altogether – Hossein Jun 18 '15 at 14:12
  • @Hossein Have you tried changing to a non-parallel loop then adding a break point inside the loop and walking through it to see where the exception is being thrown? I suspect Jon Skeet is right and you either have to copy the images to a bytearray or dispatch the access to them on the UI thread – thorkia Jun 18 '15 at 14:16
  • possible duplicate of [InvalidOperationException - object is currently in use elsewhere](http://stackoverflow.com/questions/1851292/invalidoperationexception-object-is-currently-in-use-elsewhere) – Henrik Jun 18 '15 at 14:16
  • @thorkia:Working on that at the moment – Hossein Jun 18 '15 at 14:19

1 Answers1

2

It looks like you're trying to use image APIs from non-UI threads. That's a bad idea.

I suggest you copy the image to a byte array on the UI thread, then run your parallel for loop which would mutate the array, then recreate the image afterwards from the byte array.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • If this is WPF, the other option is the use the dispatcher and invoke the calls on the UI thread – thorkia Jun 18 '15 at 14:17
  • 1
    @thorkia: But the OP is deliberately using `Parallel.For` to parallelize the work - putting each image through a UI-thread bottleneck would defeat the point. – Jon Skeet Jun 18 '15 at 14:22