2011-08-03 36 views
11

我有一個析構函數方法爲什麼我的析構函數從不運行?

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()); 
    } 
} 

當窗體被破壞,我希望它寫入到輸出窗口中的空白Winform的:

 
(Form1 opened) 
Form1.Initialize 41149443 
(Form1 closed) 
Form1.Dispose 41149443 

MSDN建議實施的析構函數3種方式:

然而,所有的這些方式寫 「Form1.Dispose 41149443」 到輸出窗口。 因此,我無法分辨表單是否已被銷燬。建議?

由於垃圾收集器的不確定性,我是否應該放棄實現這個目標的希望?

是否有另一種方法知道Form1是否被垃圾收集?

+0

爲什麼?你想做什麼? – SLaks

+0

你不能認爲析構函數會被調用。 (例如,如果你有足夠的內存,永遠不會調用任何析構函數是完全有效的。) – katrielalex

+0

是不是寫入的跟蹤? –

回答

9

只有三種實現你列舉的析構函數的方法之一實際上涉及析構函數,那就是~Destructor()

如果你實現了IDisposable,並處理你的對象,那麼Dispose的代碼將運行,但沒有理由認爲你的析構函數會。

我想你在這裏追逐不可能的東西。當垃圾收集器如此判決時,析構函數會運行。這不是你有任何控制權。 GC完全有權形成這樣的觀點:運行破壞者只是浪費時間,如果有足夠的記憶,它就會形成這種觀點。

如果您需要可預測的處置,定稿等,請使用IDisposable

+0

IDisposable不能自動預測,您必須調用Dispose或使用()。你會怎麼稱呼Dispose()? – slfan

+1

@slfan你在說什麼? 'Dispose'在調用時運行,總是通過'using'使用。我在哪裏說「Dispose」會自動運行? –

+0

你寫過「如果你需要可預測的處理......」。如果您不使用或明確調用它,則不會調用它。正如我從未使用過的表單一樣,它比終結器更難以預測。 – slfan

1

是的,您應該放棄析構函數的想法,因爲它們本質上是非確定性的。我不知道爲什麼你需要將處置爲而不是僅僅關閉,但在大多數情況下,關閉它應該足夠了。

你可以使用IDisposable但這取決於你爲什麼需要表單被垃圾收集。如果您需要重新使用它,只需創建另一個實例。

1

當沒有引用存在並且垃圾收集器恰好運行時,表單會被垃圾收集。您可以通過調用GC.Collect()來強制垃圾收集器。 您不應該在Finalizer(又名析構函數)中引用任何其他對象,因爲該對象可能已經被垃圾收集。

如果您確實需要,您可以使用內存分析工具來確定您的對象是否被垃圾收集。

您還必須記住,終結器是從主線程以外的線程調用的。

編輯: 如果你的問題是,只是你沒有看到跟蹤輸出,您可能需要開啓自動沖洗的

<configuration> 
    <system.diagnostics> 
    <trace autoflush="true" /> 
    </system.diagnostics> 
</configuration> 

編輯2: 可能存在的外部引用您的形式,如註冊的事件處理程序。我建議你在你的應用程序的管理區域,其執行下面的代碼添加一個按鈕:

GC.Collect(); 
GC.WaitForPendingFinalizers(); 
GC.Collect(); 

像這樣的垃圾收集器必須運行,應該摧毀你的表格(設置斷點到終結)。如果沒有,你可以參考一下必須銷燬的對象。

+0

是的,自動刷新仍然不能解決問題。 –

+0

好吧,試試我的第二個猜測。也許你有一些表單的參考。 – slfan

+0

我試過第二個選項,它工作。我認爲你是與其他人最接近的答案。 –

4

除非你正在研究垃圾收集,否則析構函數不是你追蹤的地方。你應該看看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#中的析構函數語法)永遠不會執行。

欲瞭解更多信息,請參閱Implementing a Dispose Method

+0

@ agent-j不應該是'「Form1.Dispose」+(處置?「處置」:「」)' – apacay

+0

@apacay,謝謝。固定 –

+0

@slfan,我的觀點是,只有在必要時才由終結者調用。如果某人明確地配置了表單,析構函數(finilize方法)可能永遠不會被執行,因爲GC.SupressFinalize。有關更多信息,請參閱Dispose模式。 –

0

您可以嘗試在WeakReference對象中包裝您的表單,然後檢查其IsAlive屬性以確定它是否已被垃圾收集。但是,是的......根據其他答案,您離開它並相信GC完成其工作可能會更好!

1

向設計師添加FormClosed事件。

即:

this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(Form1_FormClosed); 

然後創建相應的函數來處理該事件。

相關問題