"COM-объект, который был отделен от его базового RCW, не может быть использован" with.NET 4.0

у меня есть класс В моем приложении .NET 3.5 C# WinForms, который имеет пять методов. Каждый метод использует различные наборы c++ COM-интерфейсов. Использую Marshal.FinalReleaseCOMObject для очистки этих COM-объектов. Этот код отлично работает на этой платформе .NET без каких-либо проблем. Но когда я перемещаю это приложение в .NET 4.0, я начинаю получать эту ошибку в одном из этих методов в строке, где я бросаю переменную из ICOMInterface1 to ICOMInterface2, то есть:

ICOMInterface1  myVar= obj as ICOMInterface2; 

COM-объект, который был разделен от его базовой RCW не может быть используемый.

и если я удалю строку, где я использую Marshal.FinalReleaseCOMObject, Я не получаю эту ошибку.

что я пропустила? И как очистить эти неуправляемые COM-объекты из памяти на платформе .NET 4.0?

1 ответов


простой ответ никогда использовать Marshal.FinalReleaseComObject Если вы абсолютно необходимо. И если вы это сделаете, есть некоторые дополнительные правила, которым вы должны следовать.

когда COM-объект используется в .NET, среда выполнения создает то, что известно как "RCW" или "вызываемая оболочка среды выполнения" для этого объекта. Этот RCW - это обычный объект, который содержит ссылку COM на объект. Когда этот объект собирает мусор, он вызовет IUnknown::Release() на COM-объекте, как и следовало ожидать. Что это значит, если ваш COM-объект требует что последний релиз () выполняется в очень определенный момент времени, просто позвольте сборщику мусора позаботиться об этом. Многие COM-объекты попадают в этот случай, поэтому абсолютно убедитесь, что вы должны управление вызовом для выпуска() тщательно.

поэтому, когда вы вызываете FinalReleaseComObject, это по существу уменьшает ссылку RCW на COM-объект, пока он не достигнет нуля, а затем RCW освобождает COM объект. На данный момент этот RCW теперь зомбирован, и любое его использование даст исключение, которое вы видели. CLR (по умолчанию) создает только один RCW для любого базового COM-объекта, поэтому это означает, что если COM API, который вы используете, возвращает один и тот же объект дважды, у него будет только один RCW. Вызов FinalReleaseComObjectwould означать, что внезапно все использование этого RCW-это тост.

единственный способ гарантировать, что у вас есть уникальная Маршал.GetUniqueObjectForIUnknown, который предотвращает совместное использование RCW. Но, как я сказал ранее, в большинстве com APIs это не обязательно делать в первую очередь, поэтому просто не делайте этого.

пол Харрингтон написал хороший блоге о [Final]ReleaseComObject и это зло. Это опасное оружие, которое, если не понадобится, только навредит вам. Поскольку вы задаете этот вопрос, я подозреваю,что вам вообще не нужно звонить. :-)