Want to protect your cyber security and still get fast solutions? Ask a secure question today.Go Premium

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 515
  • Last Modified:

Need debugging help for InvalidOperationException

I have a program that I have simplified, but still I am getting an intermitiant crash with a NullPointer Exception.  

I have a user control derived class that displays a changing bitmap.  In the class, I have implemented a timer using System.Timers.Timer and in the Elapsed event, I call the Refresh method on the UserControl.  In the paint delegate defined on the class, I check to see if the bitmap data member of the class is null or not.  If not, I call the passed in PaintEventArgs Graphics object DrawImage method to draw the bitmap.

 But for some reason, I eventually get a NullPointerException in the DrawImage call and when I examine the bitmap and graphics objects, I see in the Quick Watch panel the value of InvalidOperationException.  I have checked the threads running and I have checked my dispose method and I am sure the object with the paint delegate being invoked is a valid object and the bitmap was just set on the object.  I even tried cloning the bitmap to be sure it is a "fresh" one so it will not get deleted out from under me.

I am at my wits end to figure out how to determine what is wrong.  I dont know what else to do to figure out why the bitmap is becoming invalid.  Can anyone tell me what might be going wrong and how I can fix it?

Is there a problem with running a worker thread and calling the Refresh method on myself?

Is there a way I can tell if the Graphics object is invalid?  Its not null, but it is also not valid?  How can I trace what caused the class to get into the broken state it seems to be in?  

I put in a global unhandled exception hander and if I run the program outside of the debugger, I get the following exception:

The object is currently in use elsewhere.

System.InvalidOperationException

Stack Trace:
   at System.Drawing.Graphics.EndContainer(GraphicsContainer container)
   at System.Windows.Forms.DibGraphicsBufferManager.ReleaseBuffer(GraphicsBuffer buffer)
   at System.Windows.Forms.GraphicsBuffer.Dispose()
   at System.Windows.Forms.Control.WmPaint(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
   at System.Windows.Forms.ContainerControl.WndProc(Message& m)
   at System.Windows.Forms.UserControl.WndProc(Message& m)
   at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)

I dont understand why this is happening or how to narrow down what is the cause.  There are no methods in my code involved with this error.  Can someone clearify what this means?

Thanks
Bryan
0
bryanwells
Asked:
bryanwells
  • 6
  • 3
1 Solution
 
Bob LearnedCommented:
Do you keep a module-level reference to the Graphics object, or do you get a reference to it on every call?

Bob
0
 
bryanwellsAuthor Commented:
I use the graphics object passed in to a paint method as a data member of the PaintEventArgs.  I dont think I am holding on to any graphics objects anywhere.  
0
 
Bob LearnedCommented:
Invalid operation with GDI+ is usually based on not having the proper Graphics object.  Since you have a confusion created by using threading, it will be tough to isolate the cause.  I am not sure that I can help you with this fairly complex problem.

Bob
0
Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

 
bryanwellsAuthor Commented:
I did some poking around on some other forums and found others had this same stack trace and it was suggested a bug in .NET involving double buffering.  Indeed, i am setting the following styles on my user control:

this.SetStyle(ControlStyles.AllPaintingInWmPaint, true);
  this.SetStyle(ControlStyles.DoubleBuffer, true);
  this.SetStyle(ControlStyles.UserPaint, true);
 
I will try "NOT" setting the double buffer style and see what happens.  Can anyone say something about this possiblity that double buffering might be a problem?

thanks
Bryan
0
 
bryanwellsAuthor Commented:
Just another note.  The problem I have described happens when I delete one instance of my user control and create another instance of the same control.  Its in the second instance that the problem shows up.  If I never delete and re-create, I dont see the problem.  Cleary, this points to a dispose-object issue, but I am very sure I am not hanging on to anything.  I simply create, use and then dispose.  And re-create.  When I dispose of the object, I stop the timer.  

I have put an ID into my objects, and i can confirm the ID of the one that gets the crash is always the second object created. I never get a paint call on the disposed object.  Perhaps the double buffering is hanging onto a graphics object after my dispose has been called.
0
 
bryanwellsAuthor Commented:
I removed the automatic double buffering and now I get the following stack trace:

Unhandled Exception:

The object is currently in use elsewhere.

System.InvalidOperationException

Stack Trace:
   at System.Drawing.Graphics.Dispose(Boolean disposing)
   at System.Drawing.Graphics.Dispose()
   at System.Windows.Forms.PaintEventArgs.Dispose(Boolean disposing)
   at System.Windows.Forms.Control.WmPaint(Message& m)
   at System.Windows.Forms.Control.WndProc(Message& m)
   at System.Windows.Forms.ScrollableControl.WndProc(Message& m)
   at System.Windows.Forms.ContainerControl.WndProc(Message& m)
   at System.Windows.Forms.UserControl.WndProc(Message& m)
   at System.Windows.Forms.ControlNativeWindow.OnMessage(Message& m)
   at System.Windows.Forms.ControlNativeWindow.WndProc(Message& m)
   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
0
 
Bob LearnedCommented:
Possible cause:

http://www.error-bank.com/microsoft.public.dotnet.languages.csharp/269266_Thread.aspx

Comment:
One possible cause for the "The object is currently in use elsewhere"
problem is if you access UI elements (forms or other controls) from non-UI
threads. If you are using multi-threaded code, then I'd double check it. One
way to do this is to put this assert as the first line of methods in your UI
classes:

   System.Diagnostics.Debug.Assert(!this.InvokeRequired, "InvokeRequired");

Then run your application and if you hit the assert, you know you've got a
threading problem. Or, if you don't hit the assert, then at least you've
ruled out this potential problem.

Bob
0
 
bryanwellsAuthor Commented:
Do you consider calling Refresh from a non-UI thread to be the case you describe?  Or does calling Refresh put the call on the main thread correctly?

Thanks
Bryan
0
 
bryanwellsAuthor Commented:
I read your suggestion and it appears I might not be able to call a user control constructor from a worker thread.  Is this the case?  I know in one case I am calling a constructor from a delegate that is responding to a use mouse event.  I will try the InvokeRequired test to see what that does.  It seems that calling a form's consructor from a delegate called from a  mouse event delegatate would be safe.
0

Featured Post

Industry Leaders: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

  • 6
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now