InvalidOperationException - object is currently in use elsewhere
There's a lock inside GDI+ that prevents two threads from accessing a bitmap at the same time. This is not a blocking kind of lock, it is a "programmer did something wrong, I'll throw an exception" kind of lock. Your threads are bombing because you are cloning the image (== accessing a bitmap) in all threads. Your UI thread is bombing because it is trying to draw the bitmap (== accessing a bitmap) at the same time a thread is cloning it.
You'll need to restrict access to the bitmap to only one thread. Clone the images in the UI thread before you start the BGWs, each BGW needs its own copy of the image. Update the PB's Image property in the RunWorkerCompleted event. You'll lose some concurrency this way but that's unavoidable.
Object is currently in use elsewhere
the locker
object is not static; thus every new instance creates its own locker; you need to create locker
as static in order to prevent access from other threads if using multiple objects.
private static Object locker = new Object();
For single object scenario, using a non static class level variable as a locker is proper. If you are employing this scenario I feel that the implementation of Singleton has some problems.
UPDATE:
public sealed class MySingleInstanceClass
{
private static volatile MySingleInstanceClass instance;
private static object syncRoot = new Object();
private Bitmap myImage;
private MySingleInstanceClass()
{
myImage = new Bitmap(100, 100);
}
public static MySingleInstanceClass Instance
{
get
{
if (instance == null)
{
lock (syncRoot)
{
if (instance == null)
instance = new MySingleInstanceClass();
}
}
return instance;
}
}
public Bitmap MyImage
{
get
{
lock (syncRoot)
return myImage;
}
private set
{
lock (syncRoot)
myImage = value;
}
}
public void Refresh()
{
lock (syncRoot)
{
var g = Graphics.FromImage(myImage);
// do more processing
}
}
}
InvalidOperationException: Object is currently in use elsewhere during innocuous onpaint?
So, I figured this out some time ago, but forgot to put the answer on here. All the customers with the problem had a single thing in common - they had installed an adobe plugin called FileOpen. It allows users to read encrypted PDFs. Turns out something FileOpen was doing (presumably to block screen captures of encrypted PDFs or something) was interfering with our application, by throwing exceptions during windows GDI+ calls (which get called from .Net OnPaint methods). In working with FileOpen, they whitelisted our application so that they wouldn't block GDI+ calls from our application.
What made this even more tricky to figure out, is that the blocking only happens after the first time you view an encrypted PDF using FileOpen... so you can have it installed and not experience the problem. If you stop their windows service FileOpenBroker, it also fixes the problem (presumably the service is what is doing the blocking).
Just posting this on here in case anyone else sees the same problem, since this was a huge headache for us at work, and took weeks to figure out.
Update:
There's a pretty easy workaround, which is to stop FileOpen's service, which is called FileOpenBroker. You should be able to find it in the list of windows services and as a process in the windows task manager. Once the process has been stopped, it stops whatever they're doing to screw up GDI+, and then you should be able to use your program until the next time you open an encrypted PDF.
It's been a while, so I don't remember for sure, but it's possible a reboot was necessary to release whatever locks they put in GDI+. I remember I built a batch file to start and stop the service, so that you could use your program without completely disabling the ability to use FileOpen (which I presume is installed because it's in use on that computer).
I just got contacted by someone else hitting this same problem, so it seems like FileOpen hasn't fixed the root problem - they only put a band-aid on it by whitelisting our particular application... fair warning.
Related Topics
How to Store Data Locally in .Net (C#)
I am Getting Failed to Load Resource: Net::Err_Blocked_By_Client with Google Chrome
Practical Applications of Bitwise Operations
Spawn Multiple Threads for Work Then Wait Until All Finished
.Net Core Di, Ways of Passing Parameters to Constructor
How to Convert Securestring to System.String
Struggling Trying to Get Cookie Out of Response with Httpclient in .Net 4.5
How to Implement Gzip Compression in ASP.NET
Handling the Window Closing Event with Wpf/Mvvm Light Toolkit
What Exactly Is an Assembly in C# or .Net
.Net - Convert Generic Collection to Datatable
Routing with Multiple Get Methods in ASP.NET Web API
How to Set Up Httpcontent for My Httpclient Postasync Second Parameter
Putting HTML Inside HTML.Actionlink(), Plus No Link Text
Foreach Loop, Determine Which Is the Last Iteration of the Loop