[英]What is the difference between the resources disposed in a finalizer to those released in dispose
這是這個問題的后續問題:
所以我明白,如果我正在創建一個使用非托管資源的類,我應該處理它們。 鏈接問題中的答案說終結器處理非托管資源。 但是, Dispose(Boolean)
方法也在處理非托管資源:
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
// get rid of unmanaged resources
}
那么終結器的處置和dispose方法的處置有什么區別呢?
您使用它的唯一原因(及其引起極大爭議)。
Dispose()
方法,則可以釋放非托管資源,從而避免泄漏。 不這樣做的原因有很多,而錯誤的原因也有很多。 簡而言之,很少有理由需要這樣做或想要這樣做
除了給出的答案:finalizer在運行時由垃圾收集器調用。
因此,您不能依賴於在終結器中釋放非托管資源的時間! 因為它是未知的。
另外,終結器在另一個線程上運行,因此當垃圾回收完成時,終結器可能仍在運行! 因此必須通過另一個垃圾回收來完全擺脫對象。
因此,第一個垃圾回收會調用finalezrs,但是不會收集對象(還有對象所引用的對象),它將在第二個垃圾回收中收集。
具有終結器的對象經歷GC的兩個階段:第一次運行終結器,第二次,實際上收集了對象並釋放了內存。 除了增加GC壓力並延遲將內存釋放回池之外,終結器還具有處理其字段可能處於無效狀態的對象的功能。 另外,在終結器線程上引發異常會立即破壞整個應用程序,而沒有任何關於發生了什么的友好信息。
這就是為什么Dispose模式實現始終以對GC.SuppressFinalize
的調用為特征的原因,如果對象已被處置並且GC可以在第一次運行時直接釋放內存,則該終結器將無法運行終結器。
通常,如果您的應用程序應能夠承受嚴重異常(例如內存不足或線程異常中止以及隨后的AppDomain卸載),則使用終結器可能會非常復雜和棘手。SQLServer或IIS等應用程序就是這種情況。
長話短說:除非絕對必要,否則不要使用終結器,並且如果必須(例如,使用非托管資源),則有很多研究在等待您。
您可以在以下博客文章中找到有關此主題的更多信息:
GC
將在對象收集之前調用~finalizer
。
這意味着對象的托管成員也將被收集或已經被收集(我不知道GC如何工作的細微差別)。
所以它已經是沒有必要的清潔管理成員,通常存在Dispose(false)
在~finalizer
,以防止它。
~B()
{
Dispose(false);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
// get rid of managed resources
}
// get rid of unmanaged resources
}
當我們通過調用Dispose()
方法或使用using
手動處置對象時,應清除對象的成員並准備進行收集(將值設置為null等)。 因此,我們在Dispose()
方法和GC.SuppressFinalize(this);
具有Dispose(true)
GC.SuppressFinalize(this);
禁用~finalizer
調用,因為在清除對象成員之后沒有必要,並且不必兩次調用Dispose(bool disposing)
。
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.