簡體   English   中英

我是否需要在托管對象上調用Dispose()?

[英]Do I need to call Dispose() on managed objects?

我無法相信我仍然對此感到困惑但是,無論如何,讓我們最終指出:

我有一個類覆蓋OnPaint來做一些繪圖。 為了加快速度,我在構造函數中預先創建了筆,畫筆等,以便OnPaint不需要繼續創建和處理它們。

現在,我確保我總是處理這些對象,但我感覺我不需要,因為盡管它們實現了IDisposable,但它們都是托管對象。

這個對嗎?


感謝所有的答案,這個問題肯定已被釘上了。
我很高興我一直保持警惕,總是使用'​​使用',所以我不需要經歷所有的代碼檢查。 我只想清楚我不是一個毫無意義的用戶。

順便說一句,我確實有一個奇怪的情況,最近,我不得不更換一個使用塊並手動調用dispose! 我會把它挖出來並創造一個新問題。

這是正確的。 您需要處置實現IDisposable對象。 這就是他們實現IDisposable - 指定它們(直接或間接)包裝非托管資源的事實。

在這種情況下,非托管資源是GDI句柄,如果在實際使用它們時未能處理它們,則會泄漏這些句柄。 現在這些特定對象具有終結器 ,這些終結器將導致在GC啟動時釋放資源,但您無法知道何時會發生這種情況。 從現在開始可能是10秒,可能是10天后; 如果你的應用程序沒有產生足夠的內存壓力導致GC啟動並在那些畫筆/筆/字體/等上運行終結器,那么在GC實現正在發生的事情之前,你最終可能會使GDI資源的操作系統挨餓。

此外,您無法保證每個非托管包裝器實際上都實現了終結器。 .NET Framework本身是非常一致的,因為實現IDisposable類使用正確的模式實現它,但是其他類完全可能有一個不包含終結器的破壞的實現,因此不能正確清理,除非在其上顯式調用Dispose 一般來說, IDisposable的目的是你不應該知道或關心具體的實現細節; 相反,如果它是一次性的,那么你處理它,期間。

故事的道德:始終處置IDisposable對象。 如果您的類“擁有” IDisposable對象,那么它應該實現IDisposable本身。

你需要處理它們。

托管對象自己管理自己的記憶 但是內存不是對象使用的唯一資源。 Dispose()旨在釋放其他資源。

你的方法有一個明顯的諷刺。 通過預先創建筆/畫筆,您正在創建 Dispose()嘗試解決的問題。 那些GDI對象將會更長,就像你不調用Dispose()時一樣。 事實上更糟糕的是,它們至少會在表格關閉之前出現。

它們可能已經足夠長,可以晉升為第二代。 垃圾收集器不經常進行第2代收集,現在重要的是在它們上調用Dispose()。 通過將表單的Dispose()方法從Designer.cs文件移動到form.cs文件並添加Dispose調用來完成此操作。

但是,這是正確的方式。 鋼筆和刷子是非常便宜的物體。 在Paint事件中,在需要時創建它們。 並使用using語句,以便它們立即處理。 使用秒表類重新確保自己這實際上不會導致任何減速。

我寫了一個GDI +圖表組件,它使用了很多筆和畫筆。 我創建了它們並將它們放在正在進行繪制的代碼塊中,性能從來都不是問題。 更好的是,在操作系統恕我直言中有一個長壽的句柄。

你有沒有對此進行分析,看看創建和處理這些對象是否確實存在問題? 我認為不是。

通過遵循create-in-a-using-block模式,您可以使自己的事情變得更容易,而且更容易出錯。

如果您確實想要創建它們一次,那么還要在您擁有的類上實現IDisposable,並在您擁有的對象上迭代Dispose。 不需要析構函數(終結器)。

對不需要Dispose的對象執行此操作幾乎沒有任何成本,但如果忘記對需要它的對象進行Dispose,則會產生很大的成本。

不,IDisposable適用於使用非托管資源的托管對象。 通常,您應該在完成后始終處置它們。

你真的需要查看刷子,筆等的文檔。

如果他們沒有使用非托管資源,您可能不必調用Dispose。 但是使用/ Dispose模式有時會被“誤用”。 作為示例,請考慮ASP.NET MVC框架。 在這里你可以這樣寫:

using(Html.BeginForm(...)){
  ///HTML input fields etc.
}

調用Html.BeginForm(...) ,將輸出FORM標記。 當using語句結束時,將在從Html.BeginForm(...)返回的對象上調用Dispose 調用Dispose會導致生成結束FORM標記。 通過這種方式,編譯器實際上將強制執行FORM標記的配對,因此您不會忘記結束標記。

不, PenBrush es 不是完全管理的對象。

它們包含非托管資源的句柄,即底層圖形系統中的相應GDI對象。 (不確定這里的確切術語......)

如果您不處理它們,在垃圾收集器完成對象之前不會釋放手柄,並且無法保證它很快就會發生,或者根本不會發生。

不,這是錯的。 我同意Aaronaught的觀點。

此外,Microsoft建議在2003年中期的Don Box網絡廣播中,每個.Net開發人員都應該處理他們自己的對象,無論是托管還是非托管,因為這會使代碼性能提高20%。 如果做得好,它可以顯着改善性能。 因此它是每個.net開發人員需要知道和使用的核心技能。

其他人提到“使用”塊用於GDI對象 - 這是一個代碼示例:

using( var bm = new Bitmap() )
using( var brush = new Brush() )
{

   // code that uses the GDI objects goes here
   ...

} // objects are automatically disposed here, even if there's an exception

請注意,您可以為單個代碼塊添加任意數量的“使用”行。

我認為這是處理Disposable對象的一種很好,干凈的方法。

在類似的帖子上看到我的答案。 如果你不打電話給Dispose,它應該解決你的問題並解釋其后果。

如果我不在Pen對象上調用Dispose會發生什么

雖然你問過鋼筆和畫筆,但Font是一個有一些奇怪怪癖的類。 特別是,如果為了設置控件的Font屬性而創建一個字體,則仍然負責處理該字體 - 所有權不會轉移到控件 - 但是可以通過處理該字體來執行該任務。任何時候 - 即使一旦創建了字體,在將其分配給控件之前。 似乎Font是托管信息對象和非托管GDI資源的組合,出於某些目的,只需要前者。 奇怪的設計 - 字體應該是兩個類。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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