Winforms 是什么导致InvalidComObjectException:“;无法使用已与其基础RCW分离的COM对象;?

Winforms 是什么导致InvalidComObjectException:“;无法使用已与其基础RCW分离的COM对象;?,winforms,interop,activex,dispose,finalizer,Winforms,Interop,Activex,Dispose,Finalizer,我已经看了各种各样的问题,其中提到了这个特殊的例外(我已经访问过)。另外,我有相同的,但在不同的背景下,所以对我没有帮助 上下文 我有一个派生自的类,它属于一个名为视图的类,它位于面板中的工作区中。我最近问了这个问题,但那个问题是针对我解决这个问题的方法是否可行。该问题的背景与此相关: .-----------------------. |Workspace | |.--------. .--------. | ||Panel1 | |Pa

我已经看了各种各样的问题,其中提到了这个特殊的例外(我已经访问过)。另外,我有相同的,但在不同的背景下,所以对我没有帮助

上下文

我有一个派生自的类,它属于一个名为
视图
的类,它位于
面板
中的
工作区
中。我最近问了这个问题,但那个问题是针对我解决这个问题的方法是否可行。该问题的背景与此相关:

.-----------------------. |Workspace | |.--------. .--------. | ||Panel1 | |Panel2 | | ||.-----. | |.-----. | | |||View1| | ||View2| | | ||'-----' | |'-----' | | |'--------' '--------' | '-----------------------' .-----------------------. |工作空间| |.--------. .--------. | ||面板1 | |面板2 || ||.-----. | |.-----. | | |||视图1 | | | |视图2 | || ||'-----' | |'-----' | | |'--------' '--------' | '-----------------------' 当一个
视图
被释放时,一个名为
Synchronize()
的方法将在所有剩余的
视图
对象上被调用。对于包含AxWindowsMediaPlayer的
视图
,它调用

问题

当我在顶层调用
Dispose()
Workspace.Dispose()
)时,如果另一个
视图
被释放,然后导致对剩余的
视图
对象调用
Synchronize()
,包含AxWindowsMediaPlayer类的
视图
videoPlayer.Error.clearErrorQueue()
行引发异常,声明:

InvalidComObjectException:无法使用已与其基础RCW分离的COM对象

我对
AxWindowsMediaPlayer
如何与其底层RCW()分离感到困惑。我读过关于打电话的危险的书。我没有显式地调用这个方法。我在
面板
视图
视频播放控制
(源自
AxWindowsMediaPlayer
)类的
Dispose
方法中设置了断点,但在异常发生之前,这些方法都不会被命中

我的解决方法是确保始终首先处理带有媒体播放器的
视图。这就是我上一个问题背后的动机。但我想了解这是如何发生的,这样我就能知道这是否是我需要解决的问题在父类上调用
Dispose
之前,是谁导致
AxWindowsMediaPlayer
与其RCW分离的?


我的猜测是,
AxWindowsMediaPlayer
终结器正在被GC调用,但我不知道是什么触发了它。出于某种原因,在更高级别调用
Dispose
会导致在地板下调用
封送.ReleaseComObject
。有人能给我点化一下吗?

不幸的是,您的解决办法就是

Control.Dispose
首先递归地处理所有ActiveX控件,然后对子控件递归调用
Dispose
。在您的示例中,如果调用
Workspace.Dispose
,将首先处理您的
AxWindowsMediaPlayer
,然后处理
Panel1
Panel2
View1
View2
(取决于您构建控件树的顺序)

我们可以通过使用来发现原因。如果我们检查
Control.Dispose
,它基本上是按如下方式实现的(注意,忽略了不相关的代码,并对其进行了轻微更改以提高可读性):

disposeAxControl
的实现方式如下:

internal virtual void DisposeAxControls()
{
    foreach (Control control in Controls)
    {
        control.DisposeAxControls();
    }
}
AxHost
类重写
disposeAxControl
以销毁托管ActiveX控件

我不太清楚为什么存在
dispeaxcontrols
函数。似乎像其他人一样,
AxHost
会简单地覆盖
Dispose
,以销毁ActiveX控件,但实际情况并非如此

internal virtual void DisposeAxControls()
{
    foreach (Control control in Controls)
    {
        control.DisposeAxControls();
    }
}