"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 и это зло. Это опасное оружие, которое, если не понадобится, только навредит вам. Поскольку вы задаете этот вопрос, я подозреваю,что вам вообще не нужно звонить. :-)