Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access a disposed object - How to fix?

In a VB.NET WinForms project, I get an exception

Cannot access a disposed of object

when closing a form. It occurs very rarely and I cannot recreate it on demand. The stack trace looks like this:

Cannot access a disposed object. Object name: 'dbiSchedule'.   at System.Windows.Forms.Control.CreateHandle()   at System.Windows.Forms.Control.get_Handle()   at System.Windows.Forms.Control.PointToScreen(Point p)   at Dbi.WinControl.Schedule.dbiSchedule.a(Boolean A_0)   at Dbi.WinControl.Schedule.dbiSchedule.a(Object A_0, EventArgs A_1)   at System.Windows.Forms.Timer.OnTick(EventArgs e)   at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)   at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam) 

The dbiSchedule is a schedule control from Dbi-tech. There is a timer on the form that updates the schedule on the screen every few minutes.

Any ideas what is causing the exception and how I might go about fixing it? or even just being able to recreate it on demand?


Hej! Thanks for all the answers. We do stop the Timer on the FormClosing event and we do check the IsDisposed property on the schedule component before using it in the Timer Tick event but it doesn't help.

It's a really annoying problem because if someone did come up with a solution that worked - I wouldn't be able to confirm the solution because I cannot recreate the problem manually.

like image 487
BTB Avatar asked Aug 27 '08 06:08

BTB


People also ask

What does Cannot access a disposed object mean?

: 'Cannot access a disposed object. A common cause of this error is disposing a context that was resolved from dependency injection and then later trying to use the same context instance elsewhere in your application.

How check object is disposed or not in C#?

Notice the check on _disposed . If you were to call a Dispose method implementing this pattern, you could call Dispose as many times as you wanted without hitting exceptions. This is not helpful. The member is private.


2 Answers

Try checking the IsDisposed property before accessing the control. You can also check it on the FormClosing event, assuming you're using the FormClosed event.

We do stop the Timer on the FormClosing event and we do check the IsDisposed property on the schedule component before using it in the Timer Tick event but it doesn't help.

Calling GC.Collect before checking IsDisposed may help, but be careful with this. Read this article by Rico Mariani "When to call GC.Collect()".

like image 71
jfs Avatar answered Sep 28 '22 12:09

jfs


It looks like a threading issue.
Hypothesis: Maybe you have the main thread and a timer thread accessing this control. The main thread shuts down - calling Control.Dispose() to indicate that I'm done with this Control and I shall make no more calls to this. However, the timer thread is still active - a context switch to that thread, where it may call methods on the same control. Now the control says I'm Disposed (already given up my resources) and I shall not work anymore. ObjectDisposed exception.

How to solve this: In the timer thread, before calling methods/properties on the control, do a check with

if ControlObject.IsDisposed then return; // or do whatever - but don't call control methods 

OR stop the timer thread BEFORE disposing the object.

like image 23
Gishu Avatar answered Sep 28 '22 12:09

Gishu