2010-10-18 60 views
2

我讀這個MSDN參考:清理Vs的內存回收在.net

雖然垃圾收集器能夠 跟蹤對象 封裝非託管資源 的壽命,它沒有具體的 關於如何清理 資源的知識。對於這些類型的對象, .NET框架提供了 Object.Finalize方法,它允許 一個目的是適當地清理其非託管 資源當垃圾 集電極回收由 對象使用的存儲器。默認情況下,Finalize 方法不起作用。如果您希望 垃圾回收器在您的對象上執行清理操作 ,然後其 回收該對象的內存,則必須 覆蓋您的 類中的Finalize方法。

我明白GC是如何工作的,但這讓我想到了實際上CleanUp是什麼?它是隻是回收內存,如果它是爲什麼它有不同的名稱?

回答

3

他們使用了一個通用的短語,比如「清理」,因爲除了回收內存之外,其他的事情可能需要完成。我可以看到這可能有點令人困惑,因爲引用提到清理資源和回憶同一句話中的記憶。在這種情況下,它們的意思是垃圾回收器回收託管代碼使用的內存,該內存實際上調用到非託管庫(例如,包裝類)中,但將非託管特定的回收過程留給開發人員(關閉文件句柄,釋放緩衝區等)。

舉個例子,我有一個包含Graph類的Graphviz包裝庫。這個類包裝了用於創建圖的函數,爲它們添加節點等。在內部,這個類保存了一個指向Graphiz自身分配的非託管圖結構的指針。對於.NET Framework,這僅僅是一個IntPtr,它不知道如何在垃圾回收期間釋放它。所以,當一個託管的對象不再被使用時,垃圾回收器釋放指針使用的內存,但不釋放它指向的數據。爲此,我必須實現一個調用非託管函數agclose(Graphviz函數釋放圖形使用的資源)的終結器。

1

例如,如果您編寫了一個使用某個操作系統資源(如命名管道或內存映射文件)的組件。您可以使用finalize操作將資源釋放回操作系統。

0

清理非託管資源可能包括關閉網絡連接,文件,數據庫連接等。當然,它也可能包括爲該資源解除分配內存。

0

CleanUp這裏的意思是釋放任何有界資源(硬盤,網絡帶寬,聲卡,內存,CPU等),由於.NET沒有託管引用非託管代碼,它可以讓你在在GC交換之前使用Finalize()方法自己正確的時刻。如果你不是CleanUp,你最終會得到一些處於未知狀態的孤立非託管代碼,這些代碼仍在使用資源。通過在您的對象上調用Dispose()來實現IDisposableCleanUp會更好。

4

請注意,這不是完整的故事,因爲最終確定只發生在對象被垃圾收集時。實際上,您應該儘快釋放所有非託管資源(文件句柄,互斥鎖,非託管內存)。您應該看看IDisposable接口,該接口定義了Dispose()函數。

只要有可能,您的垃圾處理器應該運行相同的方法來釋放終結器所需的資源,但之後會調用GC.SuppressFinalize()以阻止其再次運行(在終結器中),因爲使用實現終結器的對象時性能會受到很小的影響。