[英]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.