2011-07-15 89 views
4

一段時間以來,我在Visual Studio 2010的VSIX包中觀察到間歇性COM問題。嘗試訂閱IDE的基於COM的事件接收器之一隨機拋出以下錯誤:VSIX中令人討厭的COM互操作問題

「已從與其基礎RCW分開COM對象不能使用」

甲REPRO情況歸結爲代碼(它必須在VSIX使用,很明顯):

using System; 
using EnvDTE; 
using EnvDTE80; 

class Test 
{ 
    private readonly Events _events; 
    private readonly Events2 _events2; 
    private readonly BuildEvents _buildEvents; 
    private readonly ProjectItemsEvents _projectItemsEvents; 

    public Test(IServiceProvider provider) 
    { 
     var dte = (DTE)provider.GetService(typeof(DTE)); 
     var dte2 = (DTE2)dte; 

     // Store all references in fields as a GC precaution. 
     _events = dte.Events; 
     _events2 = (Events2)dte2.Events; 
     _buildEvents = _events.BuildEvents; 
     _projectItemsEvents = _events2.ProjectItemsEvents; 

     // Proceed to subscribe to event sinks. 
     _buildEvents.OnBuildBegin += BuildBeginHandler; // BOOM! 
     _projectItemsEvents.ItemAdded += ItemAddedHandler; 
    } 

    private void ItemAddedHandler(ProjectItem projectItem) { } 

    private void BuildBeginHandler(vsBuildScope scope, vsBuildAction action) { } 
} 

I已經從可以在網上找到的類似問題的大量描述中瞭解到可能的原因。這基本上是在COM互操作期間Runtime Callable Wrappers和GC交互方式的副作用。這是一個link到一個類似的問題完整的解釋。

我很好解釋,特別是因爲它建議一個簡單的解決方法 - 將事件接收器參考存儲在字段中,以防止過早GC。事實上,很多人似乎都以這種方式解決了他們的問題。

困擾我的是它不適用於我的情況。爲什麼我真的很難過。正如您可以清楚地看到的,我已經將所有對象引用存儲在字段中作爲預防措施。但錯誤仍然存​​在。我試圖在ctor結束時使用GC.KeepAlive()更加明確,但無濟於事。還有什麼可以做的嗎?

沒有解決方案,我的VSIX隨機加載失敗,只留下一個選項:重新啓動Visual Studio,並希望下次不會發生這種情況。

任何幫助將真正被讚賞!

回答

1

好吧,我放棄了,壓根兒唯一超出了我的想法。我認爲,由於這顯然是一種我無法以可預見的方式影響的競賽狀況,如果我輸了,我還不如重新參加比賽。

所以我感動的認購線成while循環,try .. catch -es他們試了一下Thread.Sleep()後。當這兩個訂閱都成功或者我一直持續超過2秒鐘的時間不會失去競賽時,循環退出。

踢球者是,自從我實施這個改變以來,我沒有失去過一次比賽。一個真正的Heisenbug,如果我曾見過一個。

無論如何,我會堅持這一點,直到我遇到合適的解決方案或錯誤再次出現。

+0

感謝您告訴您的解決方案。並不完全是我想聽到的,但是如果我沒有找到其他的東西,那就不得不去做。 – VitalyB

0

我懷疑你的問題實際上是你試圖連接你的事件處理程序過早。你通常需要在你的package/toolwindow/whatever的Initialize方法中做這些事情 - 一般來說,如果你需要使用你需要做的服務,如果Initialize方法被調用後,絕對不要這樣做在你的Package的構造函數中。

(這只是一種預感 - 你Test類未實現任何VSX接口,所以我不能從你的樣品時,構造函數被調用見)

+0

我在調用base.Initialize()之後,從包的Initialize中調用Test的構造函數。包類本身派生自Microsoft.VisualStudio.Project.ProjectPackage。所有一切似乎都是這樣,至少在這方面。 – aoven