无法访问已处置的对象 - 如何修复?

BTB*_*BTB 37 .net vb.net winforms

在VB.NET WinForms项目中,我得到一个例外

无法访问已处置的对象

关闭表格时.它很少发生,我无法按需重新创建它.堆栈跟踪如下所示:

Cannot access a disposed object. Object name: 'dbiSchedule'.
  at System.Windows.Forms.Control.CreateHandle()
  at System.Windows.Forms.Control.get_Handle()
  at System.Windows.Forms.Control.PointToScreen(Point p)
  at Dbi.WinControl.Schedule.dbiSchedule.a(Boolean A_0)
  at Dbi.WinControl.Schedule.dbiSchedule.a(Object A_0, EventArgs A_1)
  at System.Windows.Forms.Timer.OnTick(EventArgs e)
  at System.Windows.Forms.Timer.TimerNativeWindow.WndProc(Message& m)
  at System.Windows.Forms.NativeWindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Run Code Online (Sandbox Code Playgroud)

dbiSchedule是Dbi-tech的日程控制.表单上有一个计时器,每隔几分钟就会在屏幕上更新计划.

是什么原因导致异常以及如何修复它?或者甚至只是能够按需重新创建它?


HEJ!感谢所有的答案.我们确实在FormClosing事件上停止了Timer,我们确实检查了调度组件上的IsDisposed属性,然后在Timer Tick事件中使用它,但它没有帮助.

这是一个非常烦人的问题,因为如果有人确实提出了一个有效的解决方案 - 我将无法确认解决方案,因为我无法手动重新创建问题.

jfs*_*jfs 19

在访问控件之前,请尝试检查IsDisposed属性.您还可以在FormClosing事件上检查它,假设您正在使用FormClosed事件.

我们确实在FormClosing事件上停止了Timer,我们确实检查了调度组件上的IsDisposed属性,然后在Timer Tick事件中使用它,但它没有帮助.

在检查IsDisposed之前调用GC.Collect可能会有所帮助,但请注意这一点.阅读Rico Mariani撰写的这篇文章" 何时调用GC.Collect() ".


Gis*_*shu 10

看起来像一个线程问题.
假设:也许你有一个主线程和一个访问这个控件的计时器线程.主线程关闭 - 调用Control.Dispose()来表示我已经完成了这个控件,我将不再调用它.但是,计时器线程仍处于活动状态 - 上下文切换到该线程,它可以调用同一控件上的方法.现在控制说我已经被处置(已经放弃了我的资源),我将不再工作了.ObjectDisposed异常.

如何解决这个问题:在计时器线程中,在调用控件上的方法/属性之前,请进行检查

if ControlObject.IsDisposed then return; // or do whatever - but don't call control methods
Run Code Online (Sandbox Code Playgroud)

或者在处理对象之前停止计时器线程.

  • 检查IsDisposed将减少但不能消除问题.正确的解决方案是在关闭表单之前停止计时器. (11认同)