Подтвердить что ты не робот

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

Я пытаюсь использовать OpcRcw.da.dll. Если я вмешиваюсь в эту DLL внутри тестового консольного проекта, все работает, но если я создам проект dll для выполнения моей интерактивной гимнастики и верну свою библиотеку в свой консольный проект, я получаю эту ошибку:

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

Что нужно сделать для проекта класса lib, чтобы не убить RCW ref?

4b9b3361

Ответ 1

Несколько сложно сказать, что делает ваше фактическое приложение, но похоже, что вы можете создавать экземпляр COM-объекта, а затем пытаться получить к нему доступ из другого потока, возможно, в событие Timer.Elapsed. Если ваше приложение многопоточно, вам нужно создать экземпляр COM-объекта в каждом потоке, в котором вы его будете использовать.

Ответ 2

Это может произойти по нескольким причинам, большие из которых я знаю ниже.

Обработчики событий без сильных ссылок на делегата

Вызывающий абонент подписывается на событие на com-объекте, не сохраняя ссылки на делегат обратного вызова. Вот пример того, как это сделать правильно и как не делать этого: Причина этого - сильная ссылка должна быть удержана делегату, если она выходит за пределы области действия, оболочка освободит счетчик ссылок для интерфейса, и произойдет что-то плохое.

public class SomeClass
{
    private Interop.ComObjectWrapper comObject;
    private event ComEventHandler comEventHandler;

    public SomeClass()
    {
        comObject = new Interop.ComObjectWrapper();

        // NO - BAD!
        comObject.SomeEvent += new ComEventHandler(EventCallback);

        // YES - GOOD!
        comEventHandler = new ComEventHandler(EventCallback);
        comObject.SomeEvent += comEventHandler
    }

    public void EventCallback()
    {
        // DO WORK
    }
}

Вызовы к утилизированному оберточному устройству Runtime

Обертка была удалена, и вызовы выполняются после ее удаления. Обычно это может произойти, если элемент управления использует элемент управления activex или COM-объект, а элементы управления Dispose() выходят из строя.

  • Форма вызывает Close().
  • System.Windows.Forms.Close() вызовет Dispose()
  • Будут вызываться ваши формы virtual Dispose(), которые, надеюсь, назовут base.Dispose() где-нибудь. Systems.Windows.Forms.Dispose() освободит все COM-объекты и синхронизацию событий в форме, даже с дочерних элементов управления.
  • Если элемент управления, которому принадлежит com-объект, явно удаляется после base.Dispose(), и если он вызывает какие-либо методы на нем COM-объекте, они будут терпеть неудачу, и вы получите сообщение об ошибке "COM-объект, который был отделен от его базовый RCW не может быть использован".

Шаги отладки

Хорошим способом отладки этой проблемы является выполнение следующих действий:

  • Напишите класс, который наследуется от класса Interop (иначе известный как оболочка, вызываемая вызовом или RCW).
  • Отменить DetachEventSink
  • Переопределить Dispose
  • Вызов нового класса вместо прямого вызова класса interop
  • Добавить точку останова для DetachEventSink и Dispose
  • Посмотрите, кто нарушает порядок этих методов.

Еще одна вещь

Это не связано с этой проблемой, но пока мы находимся на этой теме, если вы не знаете иначе, всегда помните, чтобы проверить, что поток, который использует COM-объекты, отмечен STA. Вы можете сделать это, взломав отладчик и проверив возвращаемое значение:

Thread.CurrentThread.GetApartmentState();