В течение некоторого времени я наблюдал периодически возникающую проблему COM в моем пакете VSIX для Visual Studio 2010. При попытке подписаться на один из приемников событий в среде IDE в произвольном порядке выдается следующая ошибка:
«COM-объект, который был отделен от лежащего в его основе RCW, использовать нельзя»
Случай воспроизведения сводится к этому коду (который, очевидно, должен использоваться в 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) { }
}
Я узнал о возможной причине из многочисленных описаний подобных проблем, которые можно найти в сети.По сути, это побочный эффект от того, как Runtime Callable Wrappers и GC взаимодействуют во время COM-взаимодействия.Вот ссылка на похожую проблему с объяснением.
Я согласен с этим объяснением, особенно потому, что оно предлагает простой обходной путь - сохранение ссылки на приемник события в поле, чтобы предотвратить его преждевременное сборку GC.Действительно, многие люди, похоже, решили свою проблему таким образом.
Меня беспокоит то, что это не работает в моем случае .Я действительно озадачен, почему.Как вы можете видеть, я уже храню все ссылки на объекты в полях в качестве меры предосторожности.Все же ошибка все еще происходит.Я пытался быть еще более явным, используя GC.KeepAlive()
вызовы в конце ctor, но безрезультатно.Осталось ли что-нибудь еще сделать?
Без решения мой VSIX случайно не загружается, оставляя пользователю одну возможность: перезапустить Visual Studio и надеяться, что в следующий раз этого не произойдет.
Любая помощь будет по достоинству оценена!