托管客户端调用OutProc COM后,外部进程服务器exe未关闭
问题原因与解决方案
你的问题根源在于.NET COM互操作的RCW(Runtime Callable Wrapper)引用计数机制和垃圾回收的延迟特性:
- 原生C++客户端中,
IMyInterfacePtr智能指针超出作用域时会自动调用Release(),将COM对象的引用计数降到0,OutProc服务器进程因此正常退出。 - 而C#中,COM对象会被包装成RCW,.NET垃圾回收器不会在对象刚离开作用域时立即回收RCW,导致COM对象的引用计数始终无法降到0,服务器进程也就不会自动关闭。
针对托管客户端,需要做以下特殊处理:
显式释放COM对象
通过System.Runtime.InteropServices.Marshal类的方法强制释放COM引用,修改后的C#客户端代码如下:
static void Main(string[] _) { MyImpl myImpl = new MyImpl(); try { myImpl.MyMethod(); } finally { // 强制将COM对象的引用计数置为0 System.Runtime.InteropServices.Marshal.FinalReleaseComObject(myImpl); // 将对象置空,避免后续误引用 myImpl = null; // 触发垃圾回收,确保RCW被彻底清理 GC.Collect(); GC.WaitForPendingFinalizers(); } }
关键说明
FinalReleaseComObject相比ReleaseComObject更彻底,后者每次仅将引用计数减1,前者直接置0,适合确定不再使用对象的场景。- 调用
GC.Collect()和GC.WaitForPendingFinalizers()是为了确保RCW被垃圾回收器完全处理,避免残留引用导致服务器进程无法退出。 - 务必在
finally块中执行释放操作,确保即使MyMethod抛出异常,COM对象也能被正确清理。
内容的提问来源于stack exchange,提问作者srajeshnkl
相关产品推荐
相关产品推荐

