我应该在哪里处置表单所持有的托管对象?

时间:2012-07-09 20:19:36

标签: vb.net winforms dispose idisposable

如果我有一个拥有托管IDisposable对象的表单,这些对象需要在表单的生命周期内保持不变(即类级成员,也许是为了单元测试而包装和管理计时器的类) ,我什么时候应该给他们打电话Dispose()

为了提出问题(为了避免“GC会为你配置它”类型的答案),我们还假设我需要调用额外的关闭逻辑,例如:

Buffer.Flush()
Buffer.Dispose()

我可以将它放在我的部分类(Dispose())中的Form.Designer.vb方法的现有实现中,但修改该类通常是不受欢迎的。

似乎FormClosedDisposed事件是最佳选择。有理由选择一个而不是另一个吗?

3 个答案:

答案 0 :(得分:2)

“正确”的方法是将Dispose()方法从表单的Designer.vb文件移动到表单的源代码文件并进行编辑。然而,在vb.net IDE中它很尴尬,它隐藏了该文件。您必须单击“显示所有文件”图标才能看到它。

使用FormClosed是错误的,当使用ShowDialog()显示表单时,会过早地处理对象。当您检索对话框结果时,这可能会导致ObjectDisposed异常。

使用Disposed事件很好。

答案 1 :(得分:0)

在C#winforms中,我将Dispose()方法的实现从设计器移动到代码隐藏文件。从来没有遇到过这个问题。我猜你可以在VB中做同样的事情。

唯一重要的是保留处理Components集合的代码。

答案 2 :(得分:0)

一般来说,您应该尽快释放非托管资源,例如使用using语句。它通常使您的应用程序更安全,并且不会出现与资源生命周期相关的死锁和其他不当行为,而不是“习惯性地”保留资源“以防万一”或完全不必要的情况。

但是,有时您出于性能原因需要“缓存”非托管资源,或者您甚至需要出于语义原因保留一个(例如,在UI级别上互斥的一些有意锁定方案)。

在这些情况下,从父对象的Dispose调用Dispose是一个很好的约定。在这种情况下,通过处理Disposed事件。

FormClosed风险更大,因为另一个处理程序可能会阻止关闭,或者父表单的处理程序代码可能会调用此表单的方法,并且您最终可能会使用已处置的资源。再加上在整个表单上直接调用Dispose时永不释放资源的风险。

将任何代码放到FormClosed的主要优点是“更健全”的操作环境,尤其是访问父窗体。但是,很少需要处理非托管资源。