主視窗透過單例模式開啟子視窗:
// 子視窗單例
public partial class ChildForm : Form
{
static ChildForm instance;
public static ChildForm Create()
{
if (instance == null) instance = new ChildForm();
return instance;
}
}
// 主視窗選單點擊
private void menuItem_Click(object sender, EventArgs e)
{
ChildForm child = ChildForm.Create();
child.Show();
child.Focus();
}
首次開啟正常;關閉子視窗後再次點選選單 → 拋出 ObjectDisposedException。
Form.Close() 僅釋放非託管資源(視窗控制代碼),不會 將靜態欄位 instance 設為 null。instance 仍指向已 Dispose 的 ChildForm 實例,再次呼叫 Show() 時嘗試操作已釋放的控制代碼,觸發例外。
public ChildForm()
{
InitializeComponent();
this.Disposed += (s, e) => { instance = null; };
}
protected override void OnFormClosed(FormClosedEventArgs e)
{
base.OnFormClosed(e);
instance = null; // 關鍵:清除單例參考
}
OnFormClosed 在視窗完全關閉、資源釋放後觸發,比 OnClosed 更適合。
new ChildForm().Show())。Application.OpenForms 檢查)而非靜態欄位持有已釋放物件。| 概念 | 說明 |
|---|---|
| 代 | Gen 0 (短命)、Gen 1、Gen 2 (長命),分代回收提升效能 |
| 大型物件堆積 (LOH) | >= 85,000 bytes 物件直接配置於 LOH,僅 Gen 2 回收 |
| Finalize / Dispose | Finalize 非確定性;Dispose (IDisposable) 確定性釋放非託管資源 |
| GC.Collect() | 強制回收,生產環境極少主動呼叫 |