gpt4 book ai didi

c# - VSIX 中令人讨厌的 COM 互操作问题

转载 作者:行者123 更新时间:2023-11-30 12:51:34 25 4
gpt4 key购买 nike

一段时间以来,我在 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 互操作期间运行时可调用包装器和 GC 交互方式的副作用。这是一个 link一个类似的问题完整的解释。

我同意这个解释,尤其是因为它提出了一个简单的解决方法——将事件接收器引用存储在一个字段中,以防止它被过早地进行 GC。事实上,许多人似乎已经通过这种方式解决了他们的问题。

令我困扰的是它在我的情况下不起作用。我真的很困惑为什么。正如您清楚地看到的那样,作为预防措施,我已经将所有 对象引用存储在字段中。但是错误仍然存​​在。我尝试在 ctor 末尾使用 GC.KeepAlive() 调用更加明确,但无济于事。还有什么事要做吗?

如果没有解决方案,我的 VSIX 会随机加载失败,用户只有一个选择:重新启动 Visual Studio 并希望下次不会发生这种情况。

我们将不胜感激任何帮助!

最佳答案

好吧,我放弃了,只是做了我唯一想到的事情。我认为,由于这显然是我无法以可预测的方式影响的比赛条件,所以如果我输了,我还不如重新参加比赛。

所以我将订阅行移动到 while 循环中,try..catch-es 它们并在 之后重试>Thread.Sleep()。当两个订阅都成功或我连续输掉比赛超过 2 秒时,循环退出。

更重要的是,自从我实现更改以来,我还没有输过一次比赛。一个真正的 Heisenbug,如果我见过的话。

无论如何,我会坚持下去,直到我找到合适的解决方案或错误再次出现。

关于c# - VSIX 中令人讨厌的 COM 互操作问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6704776/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com