COM без регистрации не играет хорошо с однопоточными объектами. Контекст активации отброшен во время маршалинга

Я работаю над интеграцией библиотеки на основе COM/CLI в приложение на основе Java через JNI (да, это немного беспорядок). По большей части это работает, но я столкнулся с некоторым затруднением, когда дело доходит до того, как контексты активации взаимодействуют с однопоточными COM-объектами. Ситуацию, которую я имею, можно подытожить приведенным ниже фрагментом кода.

// This function, workGlue, will be called from an MTA thread.
int workGlue(int foo)
{
    ULONG_PTR cookie;
    ActivateActCtx(myActivationContext, &cookie);

    // The doWork function is part of an external library.
    // Internally it will call CoCreateInstance to create
    // a single threaded COM object which needs to be looked up
    // in the activation context.
    int result = doWork(foo);

    DeactivateActCtx(0, cookie);
    return result;
}

Развертывание библиотеки и приложения заставляет меня использовать COM без регистрации. Кроме того, поскольку основное приложение написано на Java, я не могу прикрепить ресурс манифеста к exe-файлу или что-то в этом роде. Следовательно, мне нужно использовать механизм контекста активации в COM, чтобы библиотека могла искать свои классы COM. Кроме того, сама библиотека является однопоточной, поэтому для ее работы требуется STA. Однако мое приложение будет вызывать библиотеку из всех видов потоков.

Из того, что я понимаю, COM вызовет новый "поток STA по умолчанию" при первом вызове CoCreateInstance из потока MTA, если создаваемый объект является однопоточным. Фактический объект затем создается в STA по умолчанию, и возвращаемое значение CoCreateInstance будет тогда прокси-объектом, который вызывает методы маршала назад и вперед к STA по умолчанию. Это все хорошо, и я хочу, чтобы это работало.

Моя проблема возникает, когда мой код не первый, который вызывает запуск потока STA по умолчанию. Кажется, что даже если создание объекта маршалируется в STA по умолчанию, текущий контекст активации - нет. STA по умолчанию привязан к контексту активации, который был активен во время его создания. Для меня это означает, что если я не первый, кто вызывает инициализацию STA по умолчанию, мои вызовы CoCreateInstance завершатся неудачей, поскольку STA по умолчанию не знает о моем контексте активации. Это крупное корпоративное приложение, и я не могу быть уверен, что мой код будет первым вызывать CoCreateInstance, и даже если бы я мог, это кажется мне хрупким решением.

Таким образом, мне понадобится одно из следующего:

  1. Способ маршалирования контекста активации в STA по умолчанию.

  2. Способ раскрутить новую STA с правильным контекстом активации, в котором мои объекты будут жить, и при этом вызовы CoCreateInstance и методов будут направляться туда и обратно в эту STA вместо стандартной STA.

  3. Измените мою интеграцию, чтобы убедиться, что все вызовы проблемной библиотеки поступают из одной STA, которой я управляю, чтобы избежать этапа маршалинга. Это мой резервный план, но я чувствую, что должен быть более легкий путь.

0 ответов

Другие вопросы по тегам