用C#寫了一個運用ICE組件進行接口通信的服務程序,程序運行很正常,可是在客戶端調用ICE接口時出現了大量的數據丟失,而且偶爾還通信不上,服務端最明顯的現象就是telnet服務的通信端口時不通(cmd窗口一閃而過),經過大量時間的跟蹤測試,最終只能通過tfs上的歷史修改記錄來一步一步恢復還原,最後問題定位在GC.Collect();這一句代碼上:大部份接口都存在這一句代碼進行內存回收,而把這句注掉以後,通信和數據傳輸都正常下來了!
MSDN對於強制垃圾回收的解釋:
垃圾回收 GC 類提供 GC.Collect 方法,您可以使用該方法讓應用程序在一定程度上直接控制垃圾回收器。通常情況下,您應該避免調用任何回收方法,讓垃圾回收器獨立運行。在大多數情況下,垃圾回收器在確定執行回收的最佳時機方面更有優勢。但是,在某些不常發生的情況下,強制回收可以提高應用程序的性能。當應用程序代碼中某個確定的點上使用的內存量大量減少時,在這種情況下使用 GC.Collect 方法可能比較合適。例如,應用程序可能使用引用大量非託管資源的文檔。當您的應用程序關閉該文檔時,您完全知道已經不再需要文檔曾使用的資源了。出於性能的原因,一次全部釋放這些資源很有意義。有關更多信息,請參見 GC.Collect 方法。
在垃圾回收器執行回收之前,它會掛起當前正在執行的所有線程。如果不必要地多次調用 GC.Collect,這可能會造成性能問題。您還應該注意不要將調用 GC.Collect 的代碼放置在程序中用戶可以經常調用的點上。這可能會削弱垃圾回收器中優化引擎的作用,而垃圾回收器可以確定運行垃圾回收的最佳時間。
另外做一些擴展閱讀:
首先我們要知道託管代碼中的對象什麼時候回收我們管不了(除非用GC.Collect強迫GC回收,這不推薦,後面會說明爲什麼)。GC會在它"高興"的時候執行一次回收(這有許多原因,比如內存不夠用時。這樣做是爲了提高內存分配、回收的效率)。那麼如果我們用Destructor呢?同樣不行,因爲.NET中Destructor的概念已經不存在了,它變成了Finalizer,這會在後面講到。目前請記住一個對象只有在沒有任何引用的情況下才能夠被回收。爲了說明這一點請看下面這一段代碼:[C#]object objA = new object();
object objB = objA;
objA = null;
// 強迫回收。
GC.Collect();
objB.ToString();
[Visual Basic]
Dim objA As New Object()
Dim objB As Object = objA
objA = Nothing
' 強迫回收。
GC.Collect()objB.ToString()