"Object is currently in use elsewhere" error.

I was debugging what I thought was a strange exception the other day.  The exception was an InvalidOperationException and the message was “Object is currently in use elsewhere”.  Unless you’re familiar with this exception, it really doesn’t offer much as to why the exception is occurring.  There seems to be several stale threads on the Web about this issue, so I’d thought I’d post about it.

As it turns out it had to do with some code that was PInvoking some native graphics functions and the interaction with the WinForm that was hosting the drawing surface was to blame.

What’s really happening with “Object is currently in use elsewhere” is that GDI+ is complaining that the device context (DC) that it is trying to use is already “in use”.  With WinForms, this generally means there is a recursive Graphics.GetHdc occurring.  GetHdc must match a ReleaseHdc before any other GetHdc.  Recursive means you have something like GetHdc->GetHdc->ReleaseHdc->ReleaseHdc, instead of GetHdc->ReleaseHdc->GetHdc->ReleaseHdc.  Another possibility is that there is a missing call to ReleaseHdc. (i.e. GetHdc->GetHdc->ReleaseHdc)

Now, in my case there was some seemingly innocuous code like this:

    SafeNativeMethods.DrawSomeStuff(e.Graphics.GetHdc(), parameters);

    e.Graphics.DrawString(text, this.Font, Brushes.Black, point);


…no matching ReleaseHdc(), before the DrawString call.

The fix turned out to be really simple:

    try

    {

        SafeNativeMethods.DrawSomeStuff(e.Graphics.GetHdc(), parameters);

    }

    finally

    {

        e.Graphics.ReleaseHdc();

    }

    e.Graphics.DrawString(text, this.Font, Brushes.Black, point);


You can also encounter this exception if you’re drawing to a form from multiple threads.  You’ll likely also be encountering a cross-threading exception as well.  The solution in this case is to not use multiple threads when accessing a form, including drawing.

16 thoughts on “"Object is currently in use elsewhere" error.”

  1. You could use the Icon class instead of manualling PInvoking DestroyIcon, like this:

    Icon icon = new Icon(bitmap.GetHIcon(), true);

    But, yes, that’s not intuitive… There should be an Image.GetIcon() instead that does that for you.

  2. Hi,
    I’ve the same issue not using the getHdc method, but assigning to the pictureBox Image property an Image contained in a resx file (Windows form application).

    What I cannot reach to understand is if this exception happens cause my multithread architecture or because the assignment??

    Can you help me?

  3. Hi I am calling the following method in loop, but its firing an error that object is used elsewhere.. please help .. Thanks in advance

    if (CameraGlobal.CameraOnePic.Image != null)
    {

    //Sav.Invoke(CameraGlobal.CameraOnePic.Image);
    s.Width = 240;
    s.Height = 320;
    //s = CameraGlobal.CameraOnePic
    BitMapImage = new Bitmap(CameraGlobal.CameraOnePic.Image, s);
    BitMapImage.Save(“C:\\” + CameraGlobal.ImageCount.ToString() + “.jpg”);

    //ImageList.Add(CameraGlobal.ImageCount.ToString(), CameraGlobal.CameraOnePic.Image);
    //SaveBitmap(CameraGlobal.CameraOnePic.Image);

    //SaveBitmap();
    //SaveJpeg(“C:\\2891.jpg”, CameraGlobal.CameraOnePic.Image, 1);
    // SaveBitmap(CameraGlobal.CameraOnePic.Image);
    //CameraGlobal.CameraOnePic.Invoke(new SaveImageHandler(SaveBitmap));
    //SaveBitmap(CameraGlobal.CameraOnePic.Image);
    //CameraGlobal.CameraOnePic.Image.Save(TrimPath(SurveyGlobal.PrimaryImageFilePath) + “\\” + CameraGlobal.ImageCount + “.jpg”, System.Drawing.Imaging.ImageFormat.Jpeg);
    }

  4. private void btnstart_Click(object sender, EventArgs e)
    {

    Thread grey = new Thread(new ThreadStart(greyscale));
    Thread hidden = new Thread(new ThreadStart(hide));
    Thread colour = new Thread(new ThreadStart(col));
    grey.Start();
    hidden.Start();
    colour.Start();

    }

    public void greyscale()
    {
    Bitmap grays = (Bitmap)pictureBox1.Image;
    int width = grays.Size.Width;
    int height = grays.Size.Height;

    for (int j = 0; j < height; j++)
    {
    for (int i = 0; i < width; i++)
    {
    Color col;
    col = grays.GetPixel(i, j);

    grays.SetPixel(i, j, Color.FromArgb((col.R + col.G + col.B) / 3, (col.R + col.G + col.B) / 3, (col.R + col.G + col.B) / 3));
    }
    }

    pictureBox1.Image = grays;

    }
    public void hide()
    {
    Bitmap grays1 = (Bitmap)pictureBox1.Image;
    int width1 = grays1.Size.Width;
    int height1 = grays1.Size.Height;

    for (int j = 0; j < height1; j++)
    {
    for (int i = 0; i < width1; i++)
    {
    Color col;
    col = grays1.GetPixel(i, j);

    grays1.SetPixel(i, j, Color.FromArgb(255,255,255));
    }
    }

    pictureBox1.Image = grays1;
    }

  5. @Ranjith. I’m assuming you posted that code because you’re getting the “Object is currenty in use elsewhere error”. One reason this may be happening is you’re modifying form data (pictureBox1) on a different thread from that which created the control.

    In your case, I would suggest you create a method that sets pictureBox1.Image and have it marshal itself back to the GUI thread. For example:

    private void SetImage(Bitmap bitmap)
    {
    if(InvokeRequired())
    {
    BeginInvoke((MethodInvoker)delegate() { SetImage(bitmap); });
    }
    else
    {
    pictureBox1.Image = bitmap;
    }
    }

  6. I’ve been getting this error since I moved some graphics code to a background thread.

    Every Graphics.FromImage () had a matching Dispose () call, so that wasn’t the problem.

    It was happening in the Graphics.DrawImage () method. But only the first time.

    So I put a try/catch block around the DrawImage () call, and a Thread.Sleep (5) in the catch block before trying the DrawImage () a second time. This worked. Sleep parameters <= 3 ms didn’t work.

    There’s a noticeable pause when this happens, which suggests it’s a Microsoft/.NET threading problem. Maybe it will go away in a later version of .NET.

  7. @AlanB: GDI+ (the underlying Windows library that Graphics uses) is not thread safe. Adding a Sleep() call like that, as you’ve noticed, simply slows down your code and reduces the likelihood of having another exception because it simply re-tries that code that failed and it’s less likely that another conflicting GDI+ call is being made at the very same time on another thread.

    This isn’t a solution. Since GDI+ isn’t thread-safe you need to synchronize calls to GDI+ on multiple threads. This simply means having a shared lock object and using the C# lock keyword where ever you perform GDI+ operations (i.e. around acquisition of a resource and disposal of the resource).

    Since you code isn’t the only code that can perform GDI+ operations you can’t synchronize all GDI+ code like this. This leaves you to marshal the code back to the GUI thread–which is a drastic design change from what you’ve got now.

    Long story short: you can’t perform GDI+ operations reliably on any thread other than the main (GUI) thread.

  8. @PeterRitchie: Thanks for the comments.

    In my application, drawing is required on multiple threads: The main application, and a progress bar. These use different graphics objects (for bitmaps and for the screen).

    The second thread was added specifically so a progress bar could be displayed, and the drawing could be stopped. It’s hard to see how the main thread could handle both these drawing tasks.

    Theoretically the sleep-and-retry could also throw an exception, but I haven’t seen that happen. Not even once.

  9. Hi,

    in my case I’m getting this exception because I’m using one thread that builds my Bitmap object (I’m doing some image processing and I don’t want to block my main thread…) and the “UI thread” just to display the resulting Bitmap ( = binding it to a picture box).
    Here’s a little description of what my code does:

    working thread:
    – perform some image processing
    – convert result to Bitmap
    – raise event (using Invoke) and pass the Bitmap in the EventArgs

    UI thread:
    – consumes event raised from working thread
    – takes bitmap from EventArgs and binds it to a PictureBox, this is where the exception happens.

    My question is if there is another solution than cloning the Bitmap before passing it to the UI thread?

  10. Hi there,

    I’m trying to build a program which does the following:
    when it gets a message from the Serial CommPort, it takes a picture with a webcam and saves it.
    then it looks at what color the picture has at a ROI. It sends back RGB- of the color via serial Port.

    problem:
    -taking the picture, saving it etc. works perfectly when I perform it as a button_click Event. But when I get a message of the ComPort and the SerialDataReceived_Event starts these methods, it shows: “Object is currently in use elsewhere”.

    Can someone tell me how I can fix this, or why this is happening?

    Kind Regards, Leon Netherlands

Leave a Reply

Your email address will not be published. Required fields are marked *


*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>