【问题标题】:Where can I find more detail on disposal of COM resources in .NET?在哪里可以找到有关在 .NET 中处理 COM 资源的更多详细信息?
【发布时间】:2011-09-01 00:44:07
【问题描述】:

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

我已经阅读了我在 C# 中的多代垃圾收集器、运行时可调用包装器、非托管资源内存分配、Marshal.ReleaseComObject()、Marshal.FinalReleaseComObject() 等方面可以找到的所有内容。这些都没有解释为什么应用程序当相应的 RCW 符合垃圾回收条件时,它会在非托管堆中保留活动的 COM 对象。

在一些文章中,我看到了在 C# 中垃圾收集器的实际实现可能涉及优化的可能性,例如不执行特定代中所有合格对象的收集。如果这个或类似的事情是真的,它可以解释为什么没有收集和销毁合格的 RCW 及其相应的 COM 对象。另一种解释可能是,如果非托管堆中的 COM 对象的销毁不直接与相应 RCW 的集合相关联。我还没有找到任何能提供这种程度的关于如何在 .NET 中处理 COM 对象的详细信息。我需要更好地理解这一点,因为我的应用程序的内存使用目前是不可接受的。任何指针或建议将不胜感激。

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

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

【问题讨论】:

标签: c# memory-management com


【解决方案1】:

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

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

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

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

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

【讨论】:

  • COM RCW 不是 IDisposable。
  • @BillyONEal,我没说他们是。我说过,如果你实现一个使用它们的类,你应该实现 IDisposable,然后在 Dispose 方法中清理 RCW。如果您能撤消该 -1 投票,我将不胜感激,谢谢。
  • 考虑到问题是“我如何销毁COM资源”,而这个答案并没有回答这个问题,我认为-1还是合适的。
  • 如何建设性地自己回答问题?
  • 因为我不知道答案。我来这里是想问同样的问题,发现这本来是重复的。
【解决方案2】:

使用Finalizer 或析构函数来清理 COM 对象使用的内存。

http://msdn.microsoft.com/en-us/library/66x5fx1b.aspx

或者,如果您希望立即清理对象,您可以实现 IDispose,并在您的代码中使用 using 语句来实例化 COM 对象。

【讨论】:

  • using 语句要求相关类型实现 IDisposable,而 COM RCW 没有实现。
猜你喜欢
  • 1970-01-01
  • 2016-02-08
  • 2021-06-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-03-31
相关资源
最近更新 更多