C#+ COM Interop,确定性发布

pet*_*hen 12 c# com interop

COM对象通常具有确定性破坏:在释放最后一个引用时释放它们.

如何处理C# - COM Interop?这些类没有实现IDisposable,所以我认为无法触发显式的IUnknown :: Release.

随意测试显示未引用的COM对象被懒惰地收集(即垃圾收集器触发释放).对于需要被激活释放的OCM对象,我该怎么办?(例如持有大型或共享的关键资源)?

原始问题:我们有一个C#应用程序大量使用COM库,它像疯了一样泄漏.似乎问题是"在C++和C#代码之间"(我们可以访问它们),但我们无法确定它.

Jak*_*sen 16

您可以使用System.Runtime.InteropServices.Marshal类操作COM互操作引用.具体来说,您可能需要查看Marshal.ReleaseComObject.

  • +1,因为这不止一次救了我的命. (2认同)

180*_*ION 5

我们遭受了很多苦难.最好不要尝试在.Net运行时加载太多的互操作引用.此外,Marshal.ReleaseComObject如果您需要立即发布内容,则可以使用API.

另一个好的方法是重构您的客户端代码以使用互操作代码周围的类型安全包装器 - 如果您的代码中有一个已知的引用到每个互操作RCW,这将增加interop引用将及时GC的机会.这个想要避免的主要问题是"太多点":

foo.bar.quux.xyzzy.groo(); // where foo, bar, quux and xyzzy are all COM references
Run Code Online (Sandbox Code Playgroud)

上面代码中点之间的每个对象都被有效泄露(可能不是长期运行),因为我们有一个对实例的隐式引用.您需要为每个实例创建命名引用,以便有机会清理它们:

Foo foo;
Bar bar=foo.bar;
Quux quux=bar.quux;
Xyzzy xyzzy=quux.xyzzy;
xyzzy.groo();
Run Code Online (Sandbox Code Playgroud)

现在可能使用运行时来释放引用:

ReleaseComObject(xyzzy); // etc...
Run Code Online (Sandbox Code Playgroud)