Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/300.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在哪里可以找到有关.NET中COM资源处置的更多详细信息?_C#_Memory Management_Com - Fatal编程技术网

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

C# 在哪里可以找到有关.NET中COM资源处置的更多详细信息?,c#,memory-management,com,C#,Memory Management,Com,我的问题的背景是:我正在将一个使用许多COM组件的消息处理应用程序从VB6转换为C。应用程序中的许多COM组件都是细粒度组件,在消息处理循环中使用的数量和频率都很高。与VB6应用程序相比,我发现在C#应用程序中处理一组测试消息时,内存使用量大幅(并逐渐增加)增加。我在应用程序上使用了一个内存分析器,它确认高内存使用率是由于应用程序非托管堆上的COM对象的活动实例造成的。我知道这些组件不会因为实时引用而被“泄漏”,因为如果我将GC.Collect()放在消息处理循环的核心,内存使用率将保持不变,并

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

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

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

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


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

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

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

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

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

使用或析构函数清除COM对象使用的内存


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

using
语句要求所讨论的类型实现
IDisposable
,而COM RCW没有实现。COM RCW不可IDisposable。@BillyONeal,我没说是的。我说过,如果您实现了一个使用它们的类,那么应该实现IDisposable,然后清理Dispose方法中的RCW。如果你能撤销-1投票,我将不胜感激,谢谢。考虑到这个问题是“我如何破坏COM资源”,而这个答案并没有回答这个问题,我认为-1仍然是合适的。你自己建设性地回答这个问题怎么样?因为我不知道答案。我来这里是想问同样的问题,结果发现这是一个复制品。
using(var first = new DisposableObject())
{
   ...
}