簡體   English   中英

為什么我的析構函數永遠不會運行?

[英]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種方法:

但是,這些方法都不會將“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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM