2010-12-07 47 views
1

我有一個用Visual Basic .NET應用程序通過COM互操作程序使用VB6編寫的COM組件。爲什麼我的COM組件拋出OutOfMemoryException,但在VB6上運行良好?

在VB.NET中調用時會引發OutOfMemoryException。但是,當我從Visual Basic 6應用程序運行完全相同的調用時,一切正常。

我不能在這裏發佈代碼,因爲它太長,難以遵循(我負責修復它),而且我無法確定問題所在,因爲當我嘗試從VB6調試它時, t出現。

什麼可能導致這種不同的行爲?

這工作正常,直到我使用Dictionary對象(來自Microsoft腳本運行時的COM)修復了性能問題。除非字典不合理地增長或泄漏,否則我不會看到它是如何造成這種情況的,因爲它不會增長超過100-200個元素,並且在拋出異常之前只創建一個元素。

我試着用Collection對象和一個尷尬的Exists()函數進行同樣的修復,併發生同樣的問題。如果我通過返回Nothing來提早退出,它就可以工作(即,它會拋出NullReferenceException,如預期的那樣)。

+0

是否有任何有意義的堆棧跟蹤?記憶呢?這個過程的規模是多少? – 2010-12-07 20:28:24

+0

@Simon:stacktrace結束於COM/.NET邊界。當異常飛過堆棧時,進程大約有100兆。 – 2010-12-09 19:01:20

+0

Scripting.Dictionary COM對象被標記爲STA(公寓),如以下由weloytty所述,您是否檢查了線程?順便說一下,你使用多線程訪問這本字典嗎? – 2010-12-09 19:23:38

回答

1

VB.NET中的內存管理有很大的不同。 VB6使用引用計數來釋放COM對象,VB.NET使用垃圾收集器。您可能會遇到一種情況,特別是在對組件進行單元測試時,GC不能足夠頻繁地運行以釋放COM對象。這些對象分配非託管內存,這不會對垃圾回收器施加壓力來啓動集合。

用Perfmon.exe,Performance Monitor開始診斷。右鍵單擊圖表,添加計數器,然後選擇.NET CLR內存,#Gen 0集合並選擇您的進程。確認您看到計數器以合理的速率遞增,至少每秒一個。

解決這樣的問題相當令人不快,請確保這不是由隔離組件引起的人爲問題。或者在代碼中存在一個普通的錯誤,並保留對COM對象的引用。調用GC.Collect()後跟GC.WaitForPendingFinalizers()將釋放COM對象。所以調用Marshal.ReleaseComObject()。使用GC.AddMemoryPressure()也是一種可行的解決方法,但您必須有一個合理的想法,即COM對象需要多少非託管內存。

相關問題