[英]Why does my destructor never run?
我有一个带有析构函数方法的空白Winform
public partial class Form1 : Form
{
public Form1()
{
System.Diagnostics.Trace.WriteLine("Form1.Initialize " + this.GetHashCode().ToString());
InitializeComponent();
}
~Form1()
{
System.Diagnostics.Trace.WriteLine("Form1.Dispose " + this.GetHashCode().ToString());
}
}
当表单被销毁时,我希望它写入输出窗口:
(Form1 opened) Form1.Initialize 41149443 (Form1 closed) Form1.Dispose 41149443
MSDN建议实现析构函数的3种方法:
~Destructor() http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx
IDisposable http://msdn.microsoft.com/en-us/library/system.idisposable.aspx
SafeHandle模式http://msdn.microsoft.com/en-us/library/system.runtime.interopservices.safehandle.aspx
但是,这些方法都不会将“Form1.Dispose 41149443”写入输出窗口。 因此,我无法判断表格是否已被销毁。 建议?
由于垃圾收集器的不确定性,我是否应该放弃实现这一目标的希望?
还有另一种方法可以知道Form1是否被垃圾收集?
实现你列出的析构函数的三种方法中只有一种实际上涉及析构函数,那就是~Destructor()
。
如果你实现IDisposable
并处理你的对象,那么Dispose
的代码将会运行,但没有理由认为你的析构函数会。
我想你在这里追逐不可能的事情。 析构函数在垃圾收集器如此规定时运行。 这不是你可以控制的东西。 GC完全有权形成这样的观点,即运行析构函数只会浪费时间,如果有足够的内存,它将形成这种观点。
如果您需要可预测的处理,完成等,请使用IDisposable
。
除非您正在研究垃圾收集,否则析构函数不适合您进行跟踪。 您应该查看Dispose(在Form中可覆盖)。 在释放非托管资源(如窗口句柄)之后会发生这种情况。
protected override void Dispose(bool disposing)
{
System.Diagnostics.Trace.WriteLine(
"Form1.Dispose " + (disposing ? "disposing " : "")
+ this.GetHashCode().ToString());
base.Dispose (disposing);
}
如果要查看是否已处置表单/控件,请使用Control.IsDisposed
属性。
编辑:由于GC.SuppressFinalize
,如果显式调用Dispose(或通过框架),您的Finalize方法(C#中的析构函数语法)将永远不会执行。
有关更多信息,请参阅实现Dispose方法 。
将FormClosed事件添加到设计器。
即:
this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(Form1_FormClosed);
然后创建适当的函数来处理事件。
是的,你应该放弃析构函数的想法,因为它们本质上是非确定性的。 我不知道为什么你需要有配置 ,而不是刚刚关闭的形式,而是简单地关闭它应该足够在大多数情况下。
您可以使用IDisposable
但这取决于您需要将表单垃圾回收的原因。 如果需要重新使用它,只需创建另一个实例。
当没有引用存在且垃圾收集器碰巧运行时,表单会收集垃圾。 您可以通过调用GC.Collect()强制垃圾收集器。 您不应该在Finalizer(也称为析构函数)中引用任何其他对象,因为该对象可能已经被垃圾收集。
如果确实需要,您可以使用内存分析器工具来确定您的对象是否是垃圾回收。
您还必须记住,终结器是从主线程以外的线程调用的。
编辑:如果您的问题只是您没有看到跟踪输出,您可能必须打开autoflush
<configuration>
<system.diagnostics>
<trace autoflush="true" />
</system.diagnostics>
</configuration>
编辑2:您的表单可能有外部引用,例如已注册的事件处理程序。 我建议您在应用程序的管理区域中添加一个按钮,该按钮执行以下代码:
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
像这样垃圾收集器必须运行并且应该破坏你的表单(在终结器中设置一个断点)。 如果没有,你有一些必须被销毁的对象的引用。
您可以尝试将表单包装在WeakReference对象中,然后检查其IsAlive属性以确定它是否已被垃圾回收。 但是,是的......根据其他答案,你最好离开它并相信GC能够完成它的工作!
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.