c# - 当创建它的线程终止时,COM 对象是否被 CLR 释放?

标签 c# .net vb.net com com-interop

我一直无法弄清楚如何搜索对这种怀疑的确认,但我看到证据表明在一个线程上创建的 COM 对象不再可用于其他线程(已与其底层 RCW 分离的 COM 对象不能使用)一旦代码在创建它的线程上停止执行(并且该线程可能已经终止)。这是一个真正难以追踪的问题,因为我在整个代码中都调用了 System.Runtime.InteropServices.Marshal.ReleaseComObject,但我无法确定其中任何一个被调用导致此错误。最后我得出结论,当辅助线程停止执行时,COM 对象显然被隐式释放。这是真的吗?这是记录在案的行为吗?

最佳答案

是的,COM 对象往往具有很强的线程关联性。线程不是 COM 中的次要实现细节。与 .NET 不同,COM 为 COM 类提供线程安全保证。 COM 可以发布它支持的线程类型,“单元”(即“非线程安全”)是一个非常常见的选择。 COM 确保满足这些要求,而无需程序执行任何帮助。将一个线程的调用编码到另一个线程,以便始终以线程安全的方式使用该对象是自动的。在 .NET 代码中,您通常必须自己执行此操作,例如使用 Control.BeginInvoke 或 Dispatcher.BeginInvoke。

这样做的一个自动结果是拥有一个或多个允许退出的 COM 对象的线程将自动释放这些对象。这是必要的,因为不再有办法满足线程安全要求。在此之后无论如何都要尝试使用它们会爆炸。除了确保线程保持足够长的时间以继续为这些对象提供服务之外,没有其他解决方法。同样,您需要让 UI 线程保持足够长的事件时间,以确保 Dispatcher.BeginInvoke 仍然可以在 .NET 中工作。

Fwiw,是的,使用 Marshal.ReleaseComObject() 可能会让您对此大吃一惊。显式内存管理在产生错误程序方面有着悠久的历史,而自动垃圾收集提供了解决方法。 GC 完全有能力在没有您帮助的情况下释放该 COM 对象,并且永远不会出错。只是需要更长的时间来解决它。如果您知道 COM 对象具有异常高的资源使用率,需要确定性地释放它,那么您可以对昂贵的 .NET 对象图执行完全相同的操作:GC.Collect() 有助于此。检查this answer因为 Marshal.ReleaseComObject() 往往被不必要地使用。

关于c# - 当创建它的线程终止时,COM 对象是否被 CLR 释放?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19251286/

相关文章:

c# - 你如何命名你的查询字符串变量?短还是长?为什么?

c# - struct tostring() 方法重定向到抽象类 ValueType

.net - ClickOnce 证书已过期 - 未签署 list

c# - 初始化嵌套对象属性

c# - Enumerable.Empty<T> 和 new[0] 哪个更好?

c# - 无法关闭虚拟键盘

.net - 如何记录从 Simple.Data ORM for .NET 生成的 SQL 查询

c# - 是否可以在没有“检测到文件修改”对话框的情况下从 VS 包写入当前 VS 解决方案文件

c# - 删除具有子目录(非空)的目录

c# - 如何部署 .Net Windows 应用程序