2010-01-07 72 views
6

當我意識到自己對清理資源幾乎一無所知時,我正在試驗如何擺脫應用程序中的內存泄漏。我做了一些研究,並希望只調用.dispose()將解決我所有的問題。我們的數據庫中有一張表,其中包含約65,000條記錄。顯然,當我從數據適配器填充數據集時,內存使用率可能會非常高。當我在數據集上調用dispose方法時,我驚訝地發現沒有釋放內存。爲什麼發生這種情況?清除數據集也無濟於事。.dispose()方法是否可以執行任何操作?

回答

25

IDisposable因此Dispose不用於降低內存壓力,儘管在某些情況下它可能會用於確定性清理。

請考慮這一點,您將構建一個維護與數據庫服務器的主動和開放連接的對象。此連接使用您的計算機和服務器上的資源。

當然,當你完成這個任務時,你可以將對象留下,最終它會被垃圾回收器拾取,但是假設你想確保至少釋放資源,並且因此連接關閉,當你完成它。這是IDisposableDispose進場。

它用於清理由對象管理的資源。

但是,它不會釋放分配給該對象的託管內存。這仍然留給了垃圾收集器,稍後會在這個時候啓動。

你真的有內存問題,或者你只是看看在任務管理器或類似的內存使用情況,去「有點高。」?

如果是後者,那麼你應該暫時把它留下。如果你的內存少,那麼.NET會更經常地運行垃圾回收,所以除非你處於一種情況,或者可能會懷疑你很快會遇到內存溢出的情況,否則你可能不會有任何問題。

讓我解釋我的意思是「少運行」。

如果您的計算機有8GB的內存,並且只有Windows和記事本運行,那麼大部分內存都可用。當你現在運行你的程序時,即使它將小數據塊加載到內存中,也可以長時間保持這種狀態,並且內存使用量將穩步增長。確切地說,當GC啓動並嘗試減少你的內存佔用我不知道,但我幾乎可以向你保證,你會想知道爲什麼它變得如此之高。

讓我們只是爲了爭辯說,你的程序最終會使用2GB的內存。

現在,如果你在一臺內存較少的機器上運行你的程序,GC將會更頻繁地出現,並且會降低一個下限,這可能會使內存使用量低於500MB甚至更少。

這裏要注意的重要組成部分,是爲了讓你得到多少內存應用的精確圖像實際上需要,那麼你可以不依靠任務管理器或測量它類似的方式,你需要的東西更有針對性。

+0

我的程序可以達到700,164k。考慮到我的客戶可能有低端電腦,這並不好。 – broke 2010-01-07 22:13:55

+6

這意味着你沒有閱讀我的答案。嘗試加載幾個大型應用程序,以便在啓動自己的程序之前,您的內存少於700,164k(包括虛擬內存)。然後嘗試加載它,它可能仍然有效,除非你將更多的數據加載到內存中以供使用,在這種情況下,gc根本沒有任何幫助,只需要減少處理的數據量在任何給定的時間。 – 2010-01-07 22:18:23

+0

好吧生病了試一試。 – broke 2010-01-07 22:20:30

4

調用Dispose()只會釋放非託管資源,例如文件句柄,數據庫連接,非託管內存等。它會釋放垃圾回收內存,而不是而不是

垃圾收集內存只會在下一次收集時被釋放。通常當應用程序域內存滿了時。

3

我將在這裏指出一些尚未明確提及的內容:如果組件的開發人員編寫了代碼,則調用Dispose()將只清理(免費)非託管資源。

我的意思是:如果你懷疑你有內存泄漏,呼籲Dispose()是不會解決它如果原開發商做了糟糕的工作,而不是正確地釋放非託管資源。多一點信息,check this blog post。注意聲明 Dispose的行爲由開發人員定義。

1

有些對象會要求一個或多個其他實體代表它做某件事,直到進一步通知爲止,從而損害其他實體。如果這樣做的對象在沒有通知前實體不再需要其服務的情況下消失,那些實體將繼續無用地代表不再需要它們的對象行事,繼續損害其他想要的對象使用它們。

在許多情況下,對於「喬治」對象告訴外部實體「喬」不再需要它的服務,喬治將不得不知道服務不再需要。有兩種常見的方式可以在.NET中發生,最終確定和IDIsposable

如果一個對象覆蓋了一個名爲Finalize的方法,那麼當創建該對象時,.NET垃圾回收器會將它添加到具有已註冊終結器的對象列表中。如果GC發現不存在對該列表以外的對象的根引用,則GC將從該列表中刪除該對象,並將其添加到應該儘快調用其方法的根對象強隊列中。這樣的對象然後可以使用其方法來通知其他實體不再需要其服務。

雖然基於定案的清理有時可以奏效,但並不保證及時性。在微軟的設計過程中,微軟可能已經打算將最終確定作爲主要的清理方法,但由於各種原因,它無法安全地依賴。

其他清理方法,應該是人們努力的重點,是IDisposable。基本上,IDisposable背後的想法很簡單:對於實現IDisposable的每個對象,應該有一個實體(通常是對象或嵌套執行範圍),它負責確保該對象的IDisposable.Dispose方法將在某個生命週期內的某個時間被調用宇宙(這意味着某個時候對對象的引用仍然存在),並且最好只要代碼能夠告訴對象的服務將不再需要。

請注意,IDisposable.Dispose一般承諾,任何被要求代表對象做任何事情的外部實體將被告知他們不再需要這樣做,但是這樣的承諾並不意味着實體的數量是非-零。如果一個對象沒有要求任何外部實體代表它做任何事情,那麼傳遞一個「全部」這樣的實體的消息根本不需要做任何事情。另一方面,在某些情況下,一個方法可能不會做任何事情的事實並不意味着它在任何情況下都不會做任何事情,也不意味着在它會做某件事的情況下沒有做到這一點有害影響。

相關問題