I have the following code in my worker thread (ImageListView
below is derived from Control
):
if (mImageListView != null && mImageListView.IsHandleCreated && !mImageListView.IsDisposed) { if (mImageListView.InvokeRequired) mImageListView.Invoke( new RefreshDelegateInternal(mImageListView.RefreshInternal)); else mImageListView.RefreshInternal(); }
However, I get an ObjectDisposedException
sometimes with the Invoke
method above. It appears that the control can be disposed between the time I check IsDisposed
and I call Invoke
. How can I avoid that?
What you have here is a race condition. You're better off just catching the ObjectDisposed exception and be done with it. In fact, I think in this case it is the only working solution.
try { if (mImageListView.InvokeRequired) mImageListView.Invoke(new YourDelegate(thisMethod)); else mImageListView.RefreshInternal(); } catch (ObjectDisposedException ex) { // Do something clever }
There are implicit race conditions in your code. The control can be disposed between your IsDisposed test and the InvokeRequired test. There's another one between InvokeRequired and Invoke(). You can't fix this without ensuring the control outlives the life of the thread. Given that your thread is generating data for a list view, it ought to stop running before the list view disappears.
Do so by setting e.Cancel in the FormClosing event and signaling the thread to stop with a ManualResetEvent. When the thread completes, call Form.Close() again. Using BackgroundWorker makes it easy to implement the thread completion logic, find sample code in this post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With