我已经查看了提到这个特定异常的各种问题(this question lists many of them,我已访问过)。另外,我有相同的general question as this post,但在不同的背景下,the answer对我没有帮助。
上下文
我有一个派生自AxWindowsMediaPlayer
的类,该类由名为View
的类所有,该类位于Panel
内Workspace
内。我最近询问a question这种情况,但问题是针对此问题的解决方法是否正常。该问题的背景与此相关:
.-----------------------. |Workspace | |.--------. .--------. | ||Panel1 | |Panel2 | | ||.-----. | |.-----. | | |||View1| | ||View2| | | ||'-----' | |'-----' | | |'--------' '--------' | '-----------------------'
当View
被释放时,将在所有剩余的Synchronize()
个对象上调用名为View
的方法。对于包含View
的{{1}},它会调用videoPlayer.Error.clearErrorQueue()
。
问题
当我在顶层(AxWindowsMediaPlayer
)拨打Dispose()
时,如果另一个Workspace.Dispose()
被处理掉,然后在剩余的View
上调用Synchronize()
对象,包含View
类的View
会在AxWindowsMediaPlayer
行引发异常,说明:
InvalidComObjectException:无法使用已与其基础RCW分离的COM对象。
我对videoPlayer.Error.clearErrorQueue()
如何与其基础RCW(Runtime Callable Wrapper)分离感到困惑。我看过this article that talks about this exception以及调用Marshal.ReleaseComObject()
的危险。我没有明确地称这种方法。我在AxWindowsMediaPlayer
和Dispose
以及Panel
(来自View
)类的VideoPlayerControl
方法中设置了断点,但在异常之前没有一个被击中发生的情况。
我的解决方法是确保首先处理媒体播放器的AxWindowsMediaPlayer
。这是我上一个问题背后的动机。但我想了解这是如何发生的,所以我可以看出这是否是我需要解决的问题。 在父类调用View
之前,是谁导致AxWindowsMediaPlayer
与其RCW分离?
我的猜测是Dispose
终结器被GC调用,但我不明白触发它的是什么。出于某种原因,在较高级别调用AxWindowsMediaPlayer
会导致Dispose
在地板下被调用。有人可以开导我吗?
答案 0 :(得分:3)
不幸的是,您的解决方案是解决方案。
Control.Dispose
首先以递归方式处理所有ActiveX控件,然后在子控件上递归调用Dispose
。在您的示例中,如果您致电Workspace.Dispose
,您的AxWindowsMediaPlayer
将首先处理,然后Panel1
,Panel2
,View1
,View2
(取决于在您构建控件树的顺序上。)
我们可以使用Reflector来发现原因。如果我们检查Control.Dispose
,它基本上实现如下(注意,省略了不相关的代码并略微改变以提高可读性):
protected override void Dispose(bool disposing)
{
if (disposing)
{
DisposeAxControls();
foreach (Control control in Controls)
{
control.Parent = null;
control.Dispose();
}
base.Dispose(disposing);
}
}
DisposeAxControls
实现为:
internal virtual void DisposeAxControls()
{
foreach (Control control in Controls)
{
control.DisposeAxControls();
}
}
AxHost
类会覆盖DisposeAxControls
以销毁托管的ActiveX控件。
我不确定为什么存在DisposeAxControls
函数。似乎AxHost
会像其他人一样简单地覆盖Dispose
来销毁ActiveX控件,但事实并非如此。