【发布时间】:2011-07-15 09:01:38
【问题描述】:
一段时间以来,我在 Visual Studio 2010 的 VSIX 包中发现了间歇性 COM 问题。尝试订阅 IDE 的基于 COM 的事件接收器之一随机引发以下错误:
“无法使用已与其底层 RCW 分离的 COM 对象”
复制案例归结为这段代码(显然必须在 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) { }
}
我从网上对类似问题的大量描述中了解到可能的原因。它基本上是在 COM 互操作期间 Runtime Callable Wrappers 和 GC 交互方式的副作用。这是一个类似问题的link,并附有解释。
我对这个解释很好,特别是因为它提出了一个简单的解决方法 - 将事件接收器引用存储在一个字段中,以防止它被过早地 GC'ed。确实,很多人似乎都通过这种方式解决了他们的问题。
困扰我的是它在我的情况下不起作用。我真的很困惑为什么。如您所见,我已经将 all 对象引用存储在字段中以防万一。然而错误仍然发生。我尝试在 ctor 末尾使用 GC.KeepAlive() 调用更加明确,但无济于事。还有什么事情要做吗?
如果没有解决方案,我的 VSIX 随机加载失败,用户只有一个选择:重新启动 Visual Studio 并希望下次不会发生这种情况。
任何帮助将不胜感激!
【问题讨论】:
标签: c# visual-studio com-interop vsix