.Net Framework 對於 Dispose() 有以下的不成文規定:
1. 一旦 Dispose() 過,物件的 Methods/Properties/Indexers 被呼叫時應該丟 ObjectDisposedException
2. 允許重複呼叫 Dispose()
3. Dispose() 上層物件應當會同時 Dispose() 掉他連結的下層物件 (例如 DeflateStream 以及 MemoryStream 的例子)
撰寫解構子 (Finalizer) 時有下列注意事項:
1. 請確保你的解構子可以在最短的時間內完成
2. 絕對不要在解構子裡 block 住
3. 不要在解構子裡參用其他含有解構子的物件
4. 絕對不要在解構子產生未處理的例外
5. 注意就算建構時發生例外,解構子仍然會被呼叫
6. 解構子只會被呼叫一次,除非透過 GC.ReRegisterForFinalize 來重新註冊
7. 注意解構子沒有固定的執行順序
8. 注意執行解構子的執行緒不一定只有一條
一些小知識:
Gen0 的垃圾回收通常可以在 1ms 內結束,但 Gen2 GC 可能會花超過 100ms,幸好大部分的 GC 都是 Gen0 GC。
CLR 在做 Gen0 以及 Gen1 GC 時,會 hold 住系統內所有執行緒。但 workstation version CLR(一般都是此組態) 在做 Gen2 GC 時,不會 hold 住其他執行緒。
透過 GC.Collect 可以強迫系統 GC,通常都這樣寫:
GC.Collect(); // 發動第一次 GC,不含解構子的垃圾會馬上被清除
GC.WaitForPendingFinalizers(); // 等待所有的解構子被執行
GC.Collect(); // 再發動一次 GC,含有解構子的物件會在此時被清除
CLR 具有自我調節垃圾回收演算法的機能,而程式主動 GC 會打亂這個機能。因此除非有很好的理由(例如做效能測試),否則請不要主動呼叫 GC。
沒有留言:
張貼留言