我有一个应用程序最初是用VB6编写的,我使用了一个工具将其转换为C#,从功能角度来看效果相当不错。它处理大量的消息,使用许多小到中等大小的COM(C ++)对象。
我注意到在旧的VB6应用程序中运行的特定测试运行只使用不到40M的内存,在C#应用程序中需要近900M。如果我在C#应用程序的最内层消息处理循环中放置GC.Collect(),它使用的内存与VB6应用程序相同或更少,尽管它变得非常缓慢。这使我相信在绝对意义上没有“泄漏”。
然后,我通过AQTime内存分析器运行了C#应用程序,并报告说堆上有过多的COM / C ++对象。我假设这是因为COM对象周围的运行时可调用包装很小,即使它们引用的COM对象实际上更大,它们也很少(或根本不)在C#中触发收集。我认为我可以通过在C#应用程序中添加显式的Marshal.ReleaseComObject()调用来解决这个问题。我去了很多地方做了这个,在那里COM对象的生命周期很容易确定。我注意到内存使用量仅略有减少。
我想知道为什么我没有更好的成功。查看Marshal类中的静态方法,我发现有些方法让我相信我可能错过了对COM引用处理的一些微妙之处,或者我的假设是当RCW的引用计数达到零时它们会立即被销毁是不正确的。
我希望能得到其他尝试的建议或者我可能忽视或误解的其他事情。
我注意到在旧的VB6应用程序中运行的特定测试运行只使用不到40M的内存,在C#应用程序中需要近900M。如果我在C#应用程序的最内层消息处理循环中放置GC.Collect(),它使用的内存与VB6应用程序相同或更少,尽管它变得非常缓慢。这使我相信在绝对意义上没有“泄漏”。
然后,我通过AQTime内存分析器运行了C#应用程序,并报告说堆上有过多的COM / C ++对象。我假设这是因为COM对象周围的运行时可调用包装很小,即使它们引用的COM对象实际上更大,它们也很少(或根本不)在C#中触发收集。我认为我可以通过在C#应用程序中添加显式的Marshal.ReleaseComObject()调用来解决这个问题。我去了很多地方做了这个,在那里COM对象的生命周期很容易确定。我注意到内存使用量仅略有减少。
我想知道为什么我没有更好的成功。查看Marshal类中的静态方法,我发现有些方法让我相信我可能错过了对COM引用处理的一些微妙之处,或者我的假设是当RCW的引用计数达到零时它们会立即被销毁是不正确的。
我希望能得到其他尝试的建议或者我可能忽视或误解的其他事情。