.NET 中正确释放 COM 对象
我想建议“FinalReleaseComObject”不是正确的做法。 如果你编写结构化的代码,你根本不需要它。 严格遵循 Microsoft Patterns & Practices:1) 尽可能在最后时刻声明和实例化 COM 对象。 2) 对 ALL 对象调用 ReleaseComObject(obj),并在最早可能的时刻释放。
我想建议“FinalReleaseComObject”不是正确的做法。 如果你编写结构化的代码,你根本不需要它。 严格遵循 Microsoft Patterns & Practices:1) 尽可能在最后时刻声明和实例化 COM 对象。 2) 对 ALL 对象调用 ReleaseComObject(obj),并在最早可能的时刻释放。 3) 始终以与创建相反的顺序释放 ReleaseComObject。 4) 除了调试需要外,绝不要调用 GC.Collect()。 所有这些都在 MSDN 上有文档说明。 遵循这些简单的规则后,.NET 将优化垃圾回收,从而最大限度地减少内存/垃圾负载,并提高应用程序的整体性能。 警告: GC.Collect 将停止操作系统中的所有 .NET 进程以进行垃圾回收。 每次调用 GC.Collect(),你都可能将垃圾从 Generation 0 提升到 Generation 1,然后再提升到 Generation 2。 一旦你的垃圾到达 Generation 2,你必须终止进程才能回收内存。 最后,你的代码可能需要调用 GC.Collect() 来解决泄漏代码的问题。 你可能会通过采取合法的编码捷径,无意中将隐藏的 COM 对象泄漏到垃圾中。 例如:想象一个执行工作并返回 COM 对象的 COM 函数。
在 GC 自然发生之前,myCom 将不会被完全释放。 这就是为什么这么多人需要使用 FinalReleaseComObject() 和 GC.Collect() 强制对象销毁的原因。 两者对于脏 Interop 代码都是必需的。 一个干净版本的代码
(comClass.comObject) myCom.ProcessError(errorNumber);
你的代码不需要返回的对象,它只想处理错误myCom.ProcessError(5);
Marshal.ReleaseComObject(myCom);
返回的 COM 对象被发送到 .NET 垃圾回收器,保留了对 myCom 的句柄。在 GC 自然发生之前,myCom 将不会被完全释放。 这就是为什么这么多人需要使用 FinalReleaseComObject() 和 GC.Collect() 强制对象销毁的原因。 两者对于脏 Interop 代码都是必需的。 一个干净版本的代码
Marshal.ReleaseComObject( myCom.ProcessError (5) ); //Release returned object
Marshal.ReleaseComObject( myCom);
还有许多其他的捷径,你可能会忽略集合中的项目,并且当你遵循某些 COM 对象链时,你可能会泄漏中间对象。 再次,请参考 Microsoft Patterns and Practices。