Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Cannot access a disposed object

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.

like image 763
GeorgeBoy Avatar asked Feb 10 '11 09:02

GeorgeBoy


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.

What is a disposed object C#?

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.


2 Answers

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.

like image 167
Joe Avatar answered Oct 23 '22 12:10

Joe


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.

like image 4
Øyvind Bråthen Avatar answered Oct 23 '22 12:10

Øyvind Bråthen