我有一个最初用 VB6 编写的应用程序,我使用一个工具将其转换为 C#,从功能角度来看,效果相当成功。它使用大量中小型 COM (C++) 对象处理大量消息。
我注意到旧版 VB6 应用程序中使用不到 40M 内存运行的特定测试在 C# 应用程序中需要近 900M。如果我将 GC.Collect() 放在 C# 应用程序最内部的消息处理循环中,它会使用与 VB6 应用程序相同或更少的内存,尽管它确实非常慢。这让我相信,从这个词的绝对意义上来说,不存在“泄漏”。
然后,我通过 AQTime 内存分析器运行 C# 应用程序,它报告堆上存在过多的 COM/C++ 对象。我推测这是因为 COM 对象周围的运行时可调用包装器非常小,并且从不(或很少)触发 C# 中的收集,即使它们引用的 COM 对象要大得多。我认为可以通过在 C# 应用程序中的 COM 对象周围添加显式 Marshal.ReleaseComObject() 调用来解决此问题。我在很多很容易确定 COM 对象的生命周期的地方都这样做了。我注意到内存使用量仅略有减少。
我想知道为什么我在这方面没有取得更好的成功。浏览 Marshal 类中的静态方法,我看到一些方法让我相信我可能在处理 COM 引用时遗漏了一些微妙之处,或者我认为当 RCW 的引用计数达到零时它们会立即被销毁的假设是不正确的。
如果您对我可以尝试的其他方法或我可能忽略或误解的其他事情提出任何建议,我将不胜感激。
I have an application that was originally written in VB6 that I used a tool to convert to C# with pretty good success from a functional perspective. It processes a high volume of message using lots of small to medium sized COM (C++) objects.
I noticed that a particular test run in the old VB6 app that ran using less than 40M of memory required nearly 900M in the C# app. If I put a GC.Collect() in the inner-most message processing loop of the C# app, it uses the same or less memory as the VB6 app although it is then really, really slow. This leads me to believe there is no "leak" in the absolute sense of the word.
I then ran the C# app through the AQTime memory profiler and it reported that there were an excessive number of COM/C++ objects live on the heap. I hypothesized that this was because the runtime callable wrappers around the COM objects were quite small and never (or rarely) triggered collection in C# even if their referenced COM objects were substantially larger. I thought I could address this by adding explicit Marshal.ReleaseComObject() calls around the COM objects in the C# app. I went and did this in a lot of places where the lifetime of the COM objects was easy to determine. I noticed only a very slight reduction in memory usage.
I am wondering why I did not have better success with this. Looking through the static methods in the Marshal class, I see some that lead me to believe either tha I may be missing some subtlety in the handling of COM references or that my assumption that they are immediately destroyed when the RCW's reference count reaches zero is incorrect.
I would appreciate any suggestions for other approachs that I could try or other things that I may have overlooked or misunderstood.
发布评论
评论(1)
抱歉,这个链接没有提供一个好的概要,但我自己从来没有遇到过这个问题,因为我在长期的场景中处理过 IE 和 mshtml。
文章指出:
Sorry for the link instead of a good synopsis, but I've never had that issue myself as I've dealt with IE and mshtml in a long lived scenario.
The article states: