winforms 无法访问已释放的对象

js81xvg6  于 2022-11-16  发布在  其他
关注(0)|答案(3)|浏览(300)

我面临着一个巨大的问题与"Cannot access a disposed object. Object name: 'TreeView'."错误。
在我的windows窗体上,我使用了custom windows explorer object
接下来是代码部分...
在selected node事件中,我将在所选目录中找到的图像加载到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

关于按钮关闭事件

Private Sub WizardControl1_CancelClick(ByVal sender As System.Object, ByVal e As System.ComponentModel.CancelEventArgs) Handles WizardControl1.CancelClick
        Me.Close()
 End Sub

关于窗体关闭事件

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

在调试时,我注意到当我确认关闭应用程序时,LoadImagesToFlowPreviewPanel sub中的代码继续执行。当所有图像都加载到FlowLayoutPanel控件时,会引发该错误。
接下来是堆栈跟踪...

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()

**更新:**如果所有图像都加载到FlowLayoutPanel,然后确认应用程序关闭,则不会出现错误。

busg9geu

busg9geu1#

您应该发布LoadImagesToFlowPreviewPanel方法的相关部分。
这是在没有看到代码的情况下的推测,但有一种解释可能是:

  • LoadImagesToFlowPreviewPanel正在循环中调用Application.DoEvents
  • 在对Application.DoEvents的某个调用期间,窗体关闭,TreeView被释放
  • 但循环继续执行并访问已释放的TreeView。

如果是这样的话,解决方案要么是重新设计以避免调用Application.DoEvents,要么至少在每次调用Application.DoEvents后检查Form是否关闭/ TreeView是否被释放。

更新以响应注解:

哇!实际上LoadImages是在循环内调用Application.DoEvents
如果你使用Application.DoEvents,你就暴露了代码中的重入问题--你需要非常小心,确保你理解使用它的所有后果。你描述的问题并不是你可能面临的唯一问题。我只会在非常特殊的情况下使用它,我可以保证不会有重入问题(在显示模式进度对话框时)。而且很多人会称DoEvents为“邪恶”,与此完全无关。

h5qlskok

h5qlskok2#

基本上,当你对一个已经被释放的仍然存在的对象执行操作时,就会发生这种情况。

A a = new A();
a.Dispose();
//operations performed on a will fail now

或者像这样

using( A a = new A()){
  ...
}
//operations performed on a will fail now

请记住,using块也会释放对象,就像手动调用Dispose一样。

rjee0c15

rjee0c153#

这里所要做的是启动一个处理TreeView对象的线程,然后在线程完成之前,TreeView被释放。
若要修正这个问题,请检查TreeView是否可供操作,或是未在执行绪中使用TreeView的IsDisposed属性处置。

相关问题