2011-03-14 46 views
5

我已经看过提到这个特定异常的各种问题(我访问过的this question lists many of them)。此外,我有相同的general question as this post,但在不同的上下文中,因此the answer对我没有帮助。什么导致InvalidComObjectException:“不能使用与其基础RCW分离的COM对象。”?

上下文

我已经从由一个名为View类,这是一个Panel内的国有AxWindowsMediaPlayer派生的类,一个Workspace内。我最近问这个情况a question,但是这个问题是针对我的这个问题的解决方法是否可以。从这个问题的背景是与此有关:

 
    .-----------------------. 
    |Workspace    | 
    |.--------. .--------. | 
    ||Panel1 | |Panel2 | | 
    ||.-----. | |.-----. | | 
    |||View1| | ||View2| | | 
    ||'-----' | |'-----' | | 
    |'--------' '--------' | 
    '-----------------------' 

View得到处理,一种称为Synchronize()将调用上的所有剩余View对象。对于包含AxWindowsMediaPlayerView,它调用videoPlayer.Error.clearErrorQueue()

问题

当我调用Dispose()在顶层(Workspace.Dispose()),如果另一View得到处理,然后使Synchronize()要对其余View对象调用时,View含有AxWindowsMediaPlayer类引发videoPlayer.Error.clearErrorQueue()行异常,说明:

InvalidComObjectException:已与其基础RCW分离的COM对象不能b使用。

我对AxWindowsMediaPlayer与底层RCW(Runtime Callable Wrapper)分离的方式感到困惑。我读过this article that talks about this exception以及致电Marshal.ReleaseComObject()的危险。我没有明确地调用这个方法。我已经在Dispose方法PanelViewVideoPlayerControl(来自AxWindowsMediaPlayer)类中放置了断点,但是在异常发生之前,这些方法都不会被触发。

我的解决方法是确保带有媒体播放器的View总是首先被丢弃。这是我之前的问题背后的动机。但我想了解这是如何发生的,所以我可以看到这是我需要解决的问题。 Dispose在父类上被调用之前,谁导致AxWindowsMediaPlayer与RCW分离?

我的猜测是AxWindowsMediaPlayer终结器被GC调用,但我不明白是什么触发它。由于某种原因,在较高级别呼叫Dispose正在导致Marshal.ReleaseComObject在底线下被呼叫。有人能够启发我吗?

回答

3

您的解决方法是,不幸的是,解决方案。

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

我们可以使用Reflector来发现原因。如果我们检查Control.Dispose,它基本上实现如下(注意,忽略不相关的代码,并略有改变,以提高可读性):

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

AxHost类重写DisposeAxControls

protected override void Dispose(bool disposing) 
{ 
    if (disposing) 
    { 
     DisposeAxControls(); 

     foreach (Control control in Controls) 
     { 
      control.Parent = null; 
      control.Dispose(); 
     } 

     base.Dispose(disposing); 
    } 
} 

而且DisposeAxControls为实现销毁托管的ActiveX控件。

我不太确定为什么DisposeAxControls函数存在。看起来,像其他人一样,AxHost会简单地重载Dispose以销毁ActiveX控件,但这不是如何实现的。