为什么我的COM组件抛出OutOfMemoryException,但在VB6上运行正常?

时间:2010-12-07 20:09:00

标签: .net com-interop

我有一个用VB6编写的COM组件,我通过COM互操作从Visual Basic .NET应用程序中使用。

有一种方法在从VB.NET调用时抛出OutOfMemoryException。但是,当我从Visual Basic 6应用程序运行完全相同的调用时,一切正常。

我不能在这里发布代码,因为它太长而且难以遵循(我的任务是修复它)我无法查明问题,因为当我尝试从VB6调试它时,错误不会出现。

可能导致这种不同行为的原因是什么?

这一点工作正常,直到我使用Dictionary对象(Microsoft Scripting Runtime中的COM)修复了性能问题。除非字典在不合理地增长或泄漏,否则我看不出它是如何造成这种情况的,因为它永远不会超过100-200个元素,并且只有一个在抛出异常之前创建。

我尝试使用Collection对象和一个笨拙的Exists()函数进行相同的修复,并发生同样的问题。如果我通过返回Nothing来提前拯救,它就可以工作(即,它会抛出NullReferenceException,正如预期的那样)。

2 个答案:

答案 0 :(得分:1)

VB.NET中的内存管理非常不同。 VB6使用引用计数来释放COM对象,VB.NET使用垃圾收集器。您可以进入某种情况,特别是当您对组件进行单元测试时,GC的运行频率不足以释放COM对象。这些对象分配非托管内存,不会对垃圾收集器施加压力以启动集合。

使用Perfmon.exe,性能监视器开始诊断。右键单击图形,添加计数器并选择.NET CLR内存,#Gen 0集合并选择您的过程。确认您看到计数器以合理的速率递增,至少一秒钟。

修复这样的问题是相当不愉快的,确保这不是通过隔离组件引起的人为问题。或者是代码中的一个普通错误,保留对COM对象的引用。调用GC.Collect()后跟GC.WaitForPendingFinalizers()将释放COM对象。调用Marshal.ReleaseComObject()也是如此。使用GC.AddMemoryPressure()也是一种可行的解决方法,但您必须合理地了解COM对象需要多少非托管内存。

答案 1 :(得分:0)

你有STAThread设置吗? VB6 COM组件需要STA线程,默认情况下,您的VB.NET应用程序不会运行。见http://msdn.microsoft.com/en-us/library/system.stathreadattribute(VS.71).aspx

相关问题