spurious ObjectDisposedException

G

Guest

I have two windows forms that the user toggles between; internally I show and
hide the forms. Each form is refreshed from the same thread and I use data
binding and an anonymous delegate event call to do the update.

Every once and awhile I will get the Object Disposed Exception with my form
object stated to be the culprit but when I step into the code I can step
through the delegate continue without problem so it seems the form is not
really disposed.

within class def (main thread)
public event EventHandler CPUUsagePercentChanged;
public string CPUUsagePercent { get { return
m_dCPUUsagePercent.ToString(); } }
tbCPU_Usage.DataBindings.Add("Text", this, "CPUUsagePercent");


within update thread
Invoke((MethodInvoker)delegate()
{
CPUUsagePercentChanged(sm_this, EventArgs.Empty);
});
 
G

Guest

I think you believe "disposed" means something other than it does. When a
form is "disposed," i.e. someone has called Form.Dispose() on it, the object
itself is not destroyed. It still remains until no code can access it, after
which it becomes a candidate for GC and is destroyed (this happens sooner
when you do a Release build; debug mode keeps objects around until the method
they are created in ends).

When you call Dispose() on a form, the form releases the handle given to the
form by the OS. I won't go into detail about the handle and its purpouse
here. Mostly because I'm no big win32 guru, so I don't know much about that
side of the process. Much of the form's functionality is tied to the
existance of that handle; when its gone, the form cannot communicate with the
OS anymore, kinda. So many of the form's properties and methods cannot
complete properly, and that's why some of them throw that object disposed
exception.

You have to look at your code and make sure you're not calling some of these
methods after the form has been disposed. Alternatively, you can catch the
exception and continue execution if you can gracefully recover from that
error. Post the offending code here if you need help on doing this.
 
G

Guest

Thanks for the feedback on what disposed means.

If my form is really getting disposed, why does my breakpoint in the dispose
function (the one automatically created by the wizard) never get touched?
The form continues to work fine, if the handle is really released I think it
should crash soon, certainly a nonmanaged Windows app can’t run for long with
a window with a released HWND displayed and updated. Also the handle still
shows its value, I’m not sure if it is normally set to null when released.

I suspect it is some kind of threading/garbage collection issue. I’m
calling from a monitor thread as below (Screen is a CWindowsForm derived
object). The iCurrentNavigationNode can change from the main thread, and
this is when I get my error in the Screen.monitorIO() function.

public bool monitorIO()
{
int iNode;

iNode = m_iCurrentNavigationNode;
return m_lstNavigationNodes[iNode].Screen.monitorIO();
}
 
G

Guest

That's the end of my rope. At this point I'd scrap the thread work you've
done and switch over to the BackgroundWorker object. It has some decent
inter-thread communication facilities that might avoid the problem you're
getting. Sorry I can't be of any more help.

Jeff Boeker said:
Thanks for the feedback on what disposed means.

If my form is really getting disposed, why does my breakpoint in the dispose
function (the one automatically created by the wizard) never get touched?
The form continues to work fine, if the handle is really released I think it
should crash soon, certainly a nonmanaged Windows app can’t run for long with
a window with a released HWND displayed and updated. Also the handle still
shows its value, I’m not sure if it is normally set to null when released.

I suspect it is some kind of threading/garbage collection issue. I’m
calling from a monitor thread as below (Screen is a CWindowsForm derived
object). The iCurrentNavigationNode can change from the main thread, and
this is when I get my error in the Screen.monitorIO() function.

public bool monitorIO()
{
int iNode;

iNode = m_iCurrentNavigationNode;
return m_lstNavigationNodes[iNode].Screen.monitorIO();
}


William Sullivan said:
I think you believe "disposed" means something other than it does. When a
form is "disposed," i.e. someone has called Form.Dispose() on it, the object
itself is not destroyed. It still remains until no code can access it, after
which it becomes a candidate for GC and is destroyed (this happens sooner
when you do a Release build; debug mode keeps objects around until the method
they are created in ends).

When you call Dispose() on a form, the form releases the handle given to the
form by the OS. I won't go into detail about the handle and its purpouse
here. Mostly because I'm no big win32 guru, so I don't know much about that
side of the process. Much of the form's functionality is tied to the
existance of that handle; when its gone, the form cannot communicate with the
OS anymore, kinda. So many of the form's properties and methods cannot
complete properly, and that's why some of them throw that object disposed
exception.

You have to look at your code and make sure you're not calling some of these
methods after the form has been disposed. Alternatively, you can catch the
exception and continue execution if you can gracefully recover from that
error. Post the offending code here if you need help on doing this.
 
G

Guest

I’ve done some more reading, especially Justin Roger’s WinForms UI Thread
Invokes (http://weblogs.asp.net/justin_rogers/articles/126345.aspx) and now I
wonder if there is something preventing calling the UI thread via a delegate
from another thread when form is hidden (via Hide()). Maybe there is some
lifetime issue for some temporary variable used in marshalling? When the
exception is raised, System.Windows..Forms.Control.MarshaledInvoke is the
last function in the call stack.

Jeff Boeker said:
Thanks for the feedback on what disposed means.

If my form is really getting disposed, why does my breakpoint in the dispose
function (the one automatically created by the wizard) never get touched?
The form continues to work fine, if the handle is really released I think it
should crash soon, certainly a nonmanaged Windows app can’t run for long with
a window with a released HWND displayed and updated. Also the handle still
shows its value, I’m not sure if it is normally set to null when released.

I suspect it is some kind of threading/garbage collection issue. I’m
calling from a monitor thread as below (Screen is a CWindowsForm derived
object). The iCurrentNavigationNode can change from the main thread, and
this is when I get my error in the Screen.monitorIO() function.

public bool monitorIO()
{
int iNode;

iNode = m_iCurrentNavigationNode;
return m_lstNavigationNodes[iNode].Screen.monitorIO();
}


William Sullivan said:
I think you believe "disposed" means something other than it does. When a
form is "disposed," i.e. someone has called Form.Dispose() on it, the object
itself is not destroyed. It still remains until no code can access it, after
which it becomes a candidate for GC and is destroyed (this happens sooner
when you do a Release build; debug mode keeps objects around until the method
they are created in ends).

When you call Dispose() on a form, the form releases the handle given to the
form by the OS. I won't go into detail about the handle and its purpouse
here. Mostly because I'm no big win32 guru, so I don't know much about that
side of the process. Much of the form's functionality is tied to the
existance of that handle; when its gone, the form cannot communicate with the
OS anymore, kinda. So many of the form's properties and methods cannot
complete properly, and that's why some of them throw that object disposed
exception.

You have to look at your code and make sure you're not calling some of these
methods after the form has been disposed. Alternatively, you can catch the
exception and continue execution if you can gracefully recover from that
error. Post the offending code here if you need help on doing this.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top