2011-03-14 47 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控件,但這不是如何實現的。