3

我正在通过 JNI 将基于 COM/CLI 的库集成到基于 Java 的应用程序中(是的,这有点乱)。在大多数情况下它都在工作,但是当谈到激活上下文如何与单线程 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 才能运行。但是,我的应用程序将从各种线程调用库。

据我了解,如果要创建的对象是单线程的,那么第一次从 MTA 线程调用 CoCreateInstance 时,COM 将启动一个新的“默认 STA 线程”。然后在默认 STA 中创建实际对象,然后 CoCreateInstance 的返回值将是一个代理对象,它将方法调用来回编组到默认 STA。这一切都很好,这就是我希望它的工作方式。

当我的代码不是第一个导致默认 STA 线程启动的代码时,就会出现我的问题。似乎即使对象创建被封送到默认 STA,当前激活上下文也不是。默认 STA 卡在创建时处于活动状态的激活上下文中。这对我来说意味着如果我不是第一个导致默认 STA 被初始化的人,我对 CoCreateInstance 的调用将失败,因为默认 STA 不知道我的激活上下文。这是一个大型企业应用程序,我不能确定我的代码会第一个调用 CoCreateInstance,即使我可以,这对我来说似乎也是一个脆弱的解决方案。

因此,我需要以下之一:

  1. 一种将激活上下文编组到默认 STA 的方法。

  2. 一种使用正确激活上下文启动新 STA 的方法,我的对象将在其中存在,并且 CoCreateInstance 和方法调用被来回编组到此 STA 而不是默认 STA。

  3. 重构我的集成以确保对有问题的库的所有调用都来自我可以控制的单个 STA,以避免编组步骤。这是我的备用计划,但我觉得必须有更简单的方法。

4

0 回答 0