我有一個最初用VB6編寫的應用程序,我使用了一個工具從功能角度轉換爲C#,並取得了相當不錯的成功。它使用大量小到中等大小的COM(C++)對象處理大量消息。有很多COM對象的C#中過多的內存使用
我注意到,在運行使用少於40M內存的舊VB6應用程序中運行的特定測試需要將近900M的C#應用程序。如果我將一個GC.Collect()放在C#應用程序的最內層消息處理循環中,它將使用與VB6應用程序相同或更少的內存,儘管它真的很慢。這使我相信絕對沒有「泄漏」這個詞。
然後我通過AQTime內存分析器運行C#應用程序,它報告堆中存在過多數量的COM/C++對象。我假設這是因爲COM對象周圍的運行時可調用包裝非常小,並且從不(或很少)在C#中觸發集合,即使它們引用的COM對象大得多。我想我可以通過在C#應用程序的COM對象中添加顯式的Marshal.ReleaseComObject()調用來解決這個問題。我去了很多地方,在COM對象的生命週期很容易確定的地方。我注意到內存使用量只有非常輕微的下降。
我想知道爲什麼我沒有比這更好的成功。通過查看Marshal類中的靜態方法,我看到一些讓我相信,或許我可能在處理COM引用時丟失了一些微妙之處,或者我認爲RCW的引用計數到達時它們被立即銷燬的假設是不正確的。
我希望對其他方法有任何建議,我可以嘗試或我可能忽略或誤解的其他方法。
如果你不這樣做GC.Collect的,會發生什麼?它會崩潰嗎? – 2011-03-15 02:12:28
如果我刪除GC.Collect()調用,內存使用量大約爲900M。它從來沒有崩潰,但當使用相同的COM對象時,舊的VB6應用程序使用少於40M的內存使用情況是不可接受的。 – Dan 2011-03-15 02:45:06
@Dan:它是_virtual_內存,不是物理內存。過度的分頁會比「使用」的總內存更好。 – 2011-03-15 02:47:19