2009-04-15 66 views
16

我知道,最好的做法是調用Dispose實現IDisposable的任何對象,尤其是對象用於包裝有限資源,如文件句柄,插座,GDI處理等處置字體的重要性如何?

但我遇到的情況在那裏我有一個具有Font的對象,並且我將不得不通過幾層對象來檢測IDisposable,並檢查很多用法,以確保始終獲取Font。我想知道這是否值得複雜。

如果Font包裝了HFONT,那將是一回事,因爲GDI資源是系統全局的。但是Font不包裝GDI句柄;它是GDI +,它是一個完全獨立的系統,就我所知,它是過程本地的,而不是像GDI那樣的系統全局。和Image不同的是,Font永遠不會佔據文件系統資源(無論如何我都知道)。

所以我的問題是:什麼讓字體得到垃圾收集的真正成本?

我知道我會爲終結者帶來一些小小的驚喜,但是如果「泄漏」的字體數量很少(比如說半打),那麼這個命中率並不會很明顯。除了終結器之外,這與分配一箇中等大小的陣列並讓GC清理它並沒有什麼不同 - 它只是內存。

讓我不知道讓字體得到GCed的成本?

回答

5

答案很簡單:如果只有幾個,則沒有。如果它很多,那麼是的。如果你的應用程序已經在強調垃圾收集器,那麼是的。我會使用perfmon來查看圍繞的對象數量,並將數量提升到更高一代,然後再決定。

4

問題是垃圾收集只發生在有內存壓力時。通常情況下,非託管手柄比內存更受限制,因此在GC發生之前可能會耗盡手柄,從而導致錯誤。

但是對於一個或兩個Font實例,它不會過分傷害您。

更大的問題是,有些對象是共享的,不應該(或不能)過早地佈置...

+0

「通常,非託管手柄比內存更受限制」 - 當然。但是,對於GDI +字體處理來說,這是否正確?這是我的問題的一部分。 – 2009-04-15 16:11:30

4

爲什麼你一旦完成就不處理它?僅僅因爲我們有掃街工並不意味着我們應該隨處亂扔街道。但是,在給出的例子中,如果字體在對象的生命週期中需要,則在該對象的dispose中丟棄該字體。有很多事情可以簡化我的代碼,但這並不能證明這些變化是正確的 - 有時候有些事情是你應該做的,儘管這是一種痛苦。

收拾你自己總是一個好主意。當你不再需要某些東西時,處理它。這樣您就可以避免令人討厭的競爭條件,內存不足,異常情況,繪製小故障以及冗長的處理器密集型垃圾收集。

我發現,如果你不再需要它們,除非有合理的理由不要(比如你不擁有這個物體),否則處理一次性物品是最好的做法。追蹤問題的根本原因比預先編寫代碼更困難。

至於字體,MSDN says

總是調用Dispose你釋放你的最後一個引用字體之前。否則,在垃圾回收器調用Font對象的Finalize方法之前,它所使用的資源將不會被釋放。

它不會說什麼的資源,但事實上,他們明確指出,應該是這樣的隱式添加到調用Dispose重要性。

+5

你爲什麼不處理它?那麼OP就會說爲什麼:因爲這會極大地簡化他的代碼。 – 2009-04-15 16:56:15

+2

當一個控件的Font屬性(或圖片屬性,或其他)被設置爲我持有的對象時,控件在什麼情況下創建了該對象的副本(在這種情況下,我應該處理該對象,並讓它處理它的),以及在什麼情況下控制器期望繼續使用傳入的對象?如果我有我的幹事,那麼會有一種方法來指定控制是否應該承擔所傳入對象的所有權,但由於沒有,應該怎麼做? – supercat 2010-12-22 16:44:59

1

終結器專門構建在類中,因爲清理是必要的。無論您是否需要清理大量或少量物體,最好將其清理乾淨。

GC的建立是爲了讓自己有一個假想法。通過正確處理你的對象,你可以讓GC做它做的事情。

但是,如果要創建大量字體對象並處理所有字體對象,那麼在適當的時代(可能是第0代)每隔一段時間調用一次GC以自行啓動GC清理可能會有好處取決於你在大量實例化的其他對象。你的目標應該是保存你知道自己長久以來沒有用過的物品,從而晉升到前輩。這保持了GC的工作精益&的意思。

只是用你最好的判斷,你會沒事的。但是,確實把你的正常實踐中的終結者處理掉了。

2

處置什麼東西真的有多重要?恕我直言,當你開始問這些問題時,聽起來你的代碼中有設計問題。你應該總是處理你不再需要的東西 - 這就是所謂的負責任的編程。

,您的問題可能的解決方案:

  • 不要繞過物體像Fonts在一個地方實現字體使用邏輯(一個類),將該字體添加爲該類的字段並實現該類的IDisposable

  • 實現一個字體緩存類 - 而不是在你的代碼中創建使用new運營商新Font對象,使用這個類來獲得所需的Font。如果可能的話,該類可以有邏輯重用現有的字體。或者將最後10個字體保留在內存中,並處理其他字體。爲緩存實現IDisposable,該緩存將在應用的生命週期中調用一次。

-2

我至少有一個其他應用程序運行使用.NET運行時。我不斷收到OutOfMemoryExceptions。它會很好地使你的應用程序的行爲,以便其他應用程序不能在獲得足夠的資源時拋出異常。

相關問題