c# - 在哪里可以找到有关在 .NET 中处理 COM 资源的更多详细信息?

标签 c# memory-management com

我的问题的背景是这样的:我正在将使用许多 COM 组件的消息处理应用程序从 VB6 转换为 C#。应用程序中的许多 COM 组件都是细粒度组件,它们在消息处理循环中被大量和频繁地使用。与 VB6 应用程序相比,在 C# 应用程序中处理一组测试消息时,我发现内存使用量大幅增加(并逐渐增加)。我在应用程序上使用了一个内存分析器,确认高内存使用是由于应用程序的非托管堆上 COM 对象的事件实例造成的。我知道这些组件不会由于实时引用而“泄漏”,因为如果我将 GC.Collect() 放在消息处理循环的核心,内存使用率是平坦的并且几乎与 VB6 应用程序相同(尽管性能正如人们所期望的那样可怕地退化)。

我已经阅读了我能找到的关于 C# 中的多代垃圾收集器、运行时可调用包装器、非托管资源内存分配、Marshal.ReleaseComObject()、Marshal.FinalReleaseComObject() 等的所有内容。它们都没有解释应用程序的原因当相应的 RCW 有资格进行垃圾回收时,它会保留在非托管堆中的事件 COM 对象。

在一些文章中,我看到了 C# 中垃圾收集器的实际实现可能涉及优化的可能性,例如不执行特定代中所有符合条件的对象的收集。如果这个或类似的东西是真的,它可以解释为什么不收集和销毁符合条件的 RCW 及其相应的 COM 对象。另一种解释可能是非托管堆中 COM 对象的销毁没有直接绑定(bind)到其相应 RCW 的集合。我还没有找到任何东西可以提供如此详细的 COM 对象在 .NET 中的处理方式。我需要更好地理解这一点,因为我的应用程序的内存使用量目前是 Not Acceptable 。任何指示或建议将不胜感激。

编辑: 我应该补充一点,我非常熟悉终结器(没有记录在 RCW 上存在)和 IDisposable 接口(interface)(RCW 没有实现)。据我所知,Marshal.ReleaseComObject() 是显式“处置”COM 引用的正确方法。我很小心地为我的应用程序中 COM 对象的每个已知用法添加了该语句,并且它导致内存使用没有差异。

此外,尚不清楚为什么在添加显式 GC.Collect() 不会导致内存问题时缺少处置或终结代码可能是问题所在。 Dispose() 和终结器的存在都不会导致对象的实际集合。前者允许对象抑制其终结步骤(如果有的话),后者允许清除未在 RCW 中公开的非托管资源。

最佳答案

您是否在实例化 COM 对象的类中正确实现了 IDisposable?

您需要在 Dispose() 方法中实现 IDisposable 并处理您的 COM RCW。然后,所有实例化实现 IDisposable 的类的代码都应显式调用它或使用 using() 语句调用它,如下所示:

var first = new DisposableObject();
...
first.Dispose();

using(var first = new DisposableObject())
{
   ...
}

IDisposable 是让 CLR 及时处理这些对象并确保丢失 COM 引用的唯一方法。

关于c# - 在哪里可以找到有关在 .NET 中处理 COM 资源的更多详细信息?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6112439/

相关文章:

c++ - Regex/grep/findstr 用于定位内存分配 C++

c - C中的常量变量存储在哪里?

iphone - ios 5 中何时使用强引用和弱引用

asp.net - 关于将遗留 ASP 站点与 .NET 2.0 混合的建议

c# - TabControl 的 SelectionChanged 事件问题

c# - 如何从 char 值中检索 Enum?

c#.net COM dll 中断了对 vb6 应用程序的引用

string - BSTR 和字符串

c# - 如何使用 C 程序中的现有 C# 代码

c# - 当授予类型为 ClientCredentialsFlow 时,MockIdentityServer 客户端声明不包含在访问 token 中