2011-01-14 49 views
2

之前有沒有什麼辦法讓GC.Collect的()被調用拋出一個OutOfMemoryException過嗎?調用GC.Collect拋出OutOfMemoryException異常

我想我正在尋找一種方式,它做了下面的代碼流:

Try to Allocate Memory 
On Pass Return 
Call GC.Collect() 
Try to Allocate Memory 
On Fail Throw New OutOfMemoryException() 

我正在寫一個緩存實現,目前我遇到內存不足異常所以目前解決它我使用:

If GC.GetTotalMemory(False) >= cache.CacheMemoryLimit + (100 * 1024 * 1024) Then 
    // When Total Memory exceeds CacheMemoryLimit + 100MB 
    GC.Collect() 
End If 
+4

我覺得已經運行時做了垃圾收集運行,如果你創建新對象時是內存不足。 – sisve 2011-01-14 06:02:23

+1

@Simon true,通常會拋出OutOfMemoryException,這是因爲垃圾收集器無法爲您的實例回收內存,這意味着靜態引用或其他類型的內存泄漏。由於靜態引用,Class Loader特別泄漏。 – dvhh 2011-01-14 06:15:37

回答

5

也許我不理解你的問題,但它不會是可能爲你正好趕上OutOfMemoryException異常的拋出和調用GC.Collect呢?將循環中的try/catch拋出,直到完成任務,並確保它有清理自己的能力。

bool isFinished = false; 
while (isFinished) { 
    try { 
    // do operations in here 
    } catch (OutOfMemoryException oom) { 
    GC.Collect(); 
    } 

    // if you're done... 
    isFinished = true; 
} 

請原諒使用C#僞代替VB,我儘量不要在VB中工作,除非我別無選擇。

5

的內存溢出異常的整點是讓你知道你的內存不足,之後的GC系統中所有的努力都失敗了。如果您真的在使用緩存系統,那麼您應該考慮查看弱引用或軟引用。當內存變得緊張時,這些允許系統丟棄物品,即使它們有對它們的引用。

在緩存系統中,當你查找一個對象時,你會得到結果,下一秒你會得到一個NULL,因爲內存足夠緊以迫使系統放棄弱引用對象。此時,緩存將重新創建該對象,並將其放回緩存中,然後繼續前進,就好像這是您第一次引用該對象時一樣。

5

其實.NET將愉快地拋出內存不足異常時,相反的,可能有垃圾收集和成功。這是微軟的.net實現中的幾個抱怨之一。在一個或多個線程中分配並立即丟棄大量內存的單元測試似乎通過。但是,我認爲,一旦老一代的大批老一代退出了這個領域,問題就開始了。那些東西沒有馬上拿起來。

因此,例如,如果您的代碼每次從磁盤讀取一百萬個XmlDocuments,則除非您GC.Collect()每隔幾個文檔,否則可能會出現OutOfMemory異常。

編輯:http://social.msdn.microsoft.com/forums/en-US/clr/thread/52a7eb17-ac05-470c-b063-a78427cd4406/

2

調用GC.Collect的可以修復相關定時OutOfMemory異常。 由於上面提到的Jugglist 「.NET會高興地拋出內存不足的異常,而不是它可能有垃圾回收和成功。」 我有一個高速的軟實時視頻處理系統,在重負載時偶爾會拋出OutOfMemory異常。在已知的處理死區(在下一個相機觸發器之前)中GC.Collect調用的戰略位置解決了這些問題。當然,另一種選擇是根據需要手動處理對象,但爲什麼我們使用託管環境。這個問題很可能因我的應用程序被編譯爲x86內存模型而加劇。所以,如果你正在做一些特別內存密集的事情,並且覺得你在代碼中有一席之地,你認爲做垃圾收集是合適的,那就去做吧。 這已被廣泛這裏討論:What's so wrong about using GC.Collect()?