在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)
dbiSchedule是Dbi-tech的日程控制.表单上有一个计时器,每隔几分钟就会在屏幕上更新计划.
是什么原因导致异常以及如何修复它?或者甚至只是能够按需重新创建它?
HEJ!感谢所有的答案.我们确实在FormClosing事件上停止了Timer,我们确实检查了调度组件上的IsDisposed属性,然后在Timer Tick事件中使用它,但它没有帮助.
这是一个非常烦人的问题,因为如果有人确实提出了一个有效的解决方案 - 我将无法确认解决方案,因为我无法手动重新创建问题.
在访问控件之前,请尝试检查IsDisposed属性.您还可以在FormClosing事件上检查它,假设您正在使用FormClosed事件.
我们确实在FormClosing事件上停止了Timer,我们确实检查了调度组件上的IsDisposed属性,然后在Timer Tick事件中使用它,但它没有帮助.
在检查IsDisposed之前调用GC.Collect可能会有所帮助,但请注意这一点.阅读Rico Mariani撰写的这篇文章" 何时调用GC.Collect() ".
看起来像一个线程问题.
假设:也许你有一个主线程和一个访问这个控件的计时器线程.主线程关闭 - 调用Control.Dispose()来表示我已经完成了这个控件,我将不再调用它.但是,计时器线程仍处于活动状态 - 上下文切换到该线程,它可以调用同一控件上的方法.现在控制说我已经被处置(已经放弃了我的资源),我将不再工作了.ObjectDisposed异常.
如何解决这个问题:在计时器线程中,在调用控件上的方法/属性之前,请进行检查
if ControlObject.IsDisposed then return; // or do whatever - but don't call control methods
或者在处理对象之前停止计时器线程.