2011-07-15 85 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