C# 已经与其底层 RCW 分离的 COM 对象无法使用

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2260990/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-07 00:50:35  来源:igfitidea点击:

COM object that has been separated from its underlying RCW cannot be used

c#winformscominteropmultithreading

提问by Yaron Naveh

I have some COM component which I call from some c# dll.

我有一些从 c# dll 调用的 COM 组件。

I also have a winforms app that uses that .dll.

我还有一个使用该 .dll 的 winforms 应用程序。

When I close the app I get this exception:

当我关闭应用程序时,出现此异常:

COM object that has been separated from its underlying RCW cannot be used.

不能使用与其底层 RCW 分离的 COM 对象。

The stack trace shows this exception comes from a destructor in the .dll. I implemented this destructor to call some cleanup method in the COM.

堆栈跟踪显示此异常来自 .dll 中的析构函数。我实现了这个析构函数来调用 COM 中的一些清理方法。

Why does this happen? How is it best to solve it?

为什么会发生这种情况?怎么解决最好?

采纳答案by Ran

The issue is described here:

此处描述了该问题:

Is it safe to call an RCW from a finalizer?

从终结器调用 RCW 是否安全?

and here:

和这里:

Release Excel Object In My Destructor

在我的析构函数中释放 Excel 对象

The trouble is that not only is the timing as to when these objects are to be garbage collected uncertain, but the order in which the finalizers are called is also nondeterministic. In this case, a Runtime Callable Wrapper also has a finalizer, which calls Marshal.FinalReleaseComObject on itself, which has the result of decrementing the reference count on the COM side of the fence so that this COM object can be released. But since the order in which the finalizers are called is uncertain, it is very possible that the finalizers for the COM objects that your object references will fire before the finalizer for your object. So the code within your finalizer could work sometimes, but, most of the time, one or more of the Runtime Callable Wrappers that your object references will have already had their finalizers called and the underlying COM object will have been released before your finalizer gets to execute its code.

问题在于,不仅这些对象何时被垃圾回收的时间不确定,而且调用终结器的顺序也是不确定的。在这种情况下,Runtime Callable Wrapper 也有一个终结器,它对自身调用 Marshal.FinalReleaseComObject,其结果是在栅栏的 COM 端递减引用计数,以便可以释放此 COM 对象。但是由于调用终结器的顺序是不确定的,对象引用的 COM 对象的终结器很可能会在对象的终结器之前触发。所以你的终结器中的代码有时可以工作,但是,大多数时候,