i am facing a huge problem with the "Cannot access a disposed object. Object name: 'TreeView'."
error.
On a windows forms of mine i use a custom windows explorer object.
And here come the code parts...
On the selected node event, i load the images found within the selected directory to the FlowLayoutPanel.
Private Sub ExpTree1_ExpTreeNodeSelected(ByVal SelPath As String, ByVal Item As ExplorerControls.CShItem) Handles ExpTree1.ExpTreeNodeSelected
'Loop until all images are loaded.
LoadImagesToFlowPreviewPanel()
End Sub
On the button close event
Private Sub WizardControl1_CancelClick(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles WizardControl1.CancelClick
Me.Close()
End Sub
On the Form Closing event
Private Sub Wizard_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing
Select Case XtraMessageBox.Show("Exit the application?", Me.Text, MessageBoxButtons.YesNo, MessageBoxIcon.Question)
Case Windows.Forms.DialogResult.No
e.Cancel = True
End Select
End If
End Sub
While debugging i noticed that when i confirm closing the application, the code within the LoadImagesToFlowPreviewPanel
sub continues to execute. The error is raised when all the images are loaded to the FlowLayoutPanel control.
And here comes the stack trace...
at System.Windows.Forms.Control.CreateHandle()
at System.Windows.Forms.TreeView.CreateHandle()
at System.Windows.Forms.Control.get_Handle()
at System.Windows.Forms.TreeView.TvnSelected(NMTREEVIEW* nmtv)
at System.Windows.Forms.TreeView.WmNotify(Message& m)
at System.Windows.Forms.TreeView.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.SendMessage(HandleRef hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.Control.SendMessage(Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.Control.ReflectMessageInternal(IntPtr hWnd, Message& m)
at System.Windows.Forms.Control.WmNotify(Message& m)
at System.Windows.Forms.Control.WndProc(Message& m)
at System.Windows.Forms.Application.ParkingWindow.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.CallWindowProc(IntPtr wndProc, IntPtr hWnd, Int32 msg, IntPtr wParam, IntPtr lParam)
at System.Windows.Forms.NativeWindow.DefWndProc(Message& m)
at System.Windows.Forms.TreeView.WmMouseDown(Message& m, MouseButtons button, Int32 clicks)
at System.Windows.Forms.TreeView.WndProc(Message& m)
at System.Windows.Forms.Control.ControlNativeWindow.WndProc(Message& m)
at System.Windows.Forms.NativeWindow.DebuggableCallback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
at System.Windows.Forms.UnsafeNativeMethods.DispatchMessageW(MSG& msg)
at System.Windows.Forms.Application.ComponentManager.System.Windows.Forms.UnsafeNativeMethods.IMsoComponentManager.FPushMessageLoop(Int32 dwComponentID, Int32 reason, Int32 pvLoopData)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoopInner(Int32 reason, ApplicationContext context)
at System.Windows.Forms.Application.ThreadContext.RunMessageLoop(Int32 reason, ApplicationContext context)
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.OnRun()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.DoApplicationModel()
at Microsoft.VisualBasic.ApplicationServices.WindowsFormsApplicationBase.Run(String[] commandLine)
at CannonUpdater.My.MyApplication.Main(String[] Args) in 17d14f5c-a337-4978-8281-53493378c1071.vb:line 82
at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
at System.Runtime.Hosting.ApplicationActivator.CreateInstance(ActivationContext activationContext, String[] activationCustomData)
at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssemblyDebugInZone()
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ThreadHelper.ThreadStart()
UPDATE: IF all the images are loaded to the FlowLayoutPanel
and the confirmation of the application close comes next, i get no error.
: '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.
In the context of C#, dispose is an object method invoked to execute code required for memory cleanup and release and reset unmanaged resources, such as file handles and database connections.
You should post the relevant parts of your LoadImagesToFlowPreviewPanel
method.
This is speculation without seeing the code, but one explanation could be:
LoadImagesToFlowPreviewPanel is calling Application.DoEvents
in a loop
The Form is closed and the TreeView disposed during one of the calls to Application.DoEvents
But the loop continues to execute and accesses the disposed TreeView.
If it was this, the solution would be either a redesign to avoid calling Application.DoEvents
, or at least checking if the Form is closed / TreeView is disposed after every call to Application.DoEvents
.
UPDATE in response to comment:
Wow! Actually the LoadImages is calling the Application.DoEvents within a loop
If you use Application.DoEvents
you expose yourself to reentrancy problems in your code - you need to be very careful and make sure you understand all the consequences when you use it. The issue you described is not the only problem you're likely to face. I would only use it in very specific cases where I can guarantee not to have reentrancy problems (e.g. while a modal progress dialog is displayed). And many people will call DoEvents
"evil" and have nothing to do with it at all.
Basically this happens when you perform an operation on a object that is still alive that you have disposed. So either like this:
A a = new A();
a.Dispose();
//operations performed on a will fail now
Or like this
using( A a = new A()){
...
}
//operations performed on a will fail now
Remember that a using block will also dispose your object just like manually calling Dispose.
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