gpt4 book ai didi

multithreading - COM 对象方法不在 CoInitialize-d 并创建对象的线程上执行

转载 作者:行者123 更新时间:2023-12-04 08:25:55 25 4
gpt4 key购买 nike

我正在开发一个 UI 应用程序,它会一路创建一个 COM 对象。
问题是,我想将这个 COM 对象完全“移动”到另一个线程上。

我要做的是:

  • 创建我想将对象移动到的新线程(使用 CreateThread API)
  • 进入此线程后,我正在调用 PeekMessage 为其设置消息队列
  • 调用CoInitialize,CoCreateInstance创建COM对象,QueryInterface得到我想要的接口(interface)
  • 最后,我在界面上调用一个方法,该方法显示一个带有 GetCurrentThreadId() 返回值的 MessageBox(我可以访问该对象所在的 COM 库的 VB6 代码)。

  • 问题是,正如此消息框所示,对象方法仍然在原始 UI 线程上执行,而不是在我创建并完成所有这些步骤的线程上执行。还要提一提,在调用了接口(interface)方法之后,我还在里面设置了一个经典的消息循环。

    我怎样才能改变这种行为并实现我想要的? (也就是说,我希望源自我新创建的线程的 COM 对象调用在 IT 上执行,而不是在原始应用程序线程上执行)

    这是一些伪代码,使其更加清晰:
    void myMainUIMethod(){
    MessageBox(GetCurrentThreadId()); // displays 1
    CreateThread(&myCOMObjectThreadProc);
    }
    void myCOMObjectThreadProc(){
    MessageBox(GetCurrentThreadId()); // displays 2
    CoInitialize(NULL);
    myObject = CoCreateInstance(myObjectsCLSID);
    myObjectInterface = myObject->QueryInterface(myObjectInterfaceCLSID);
    myObjectInterface->showThreadIDMessageBox(); // this would be the COM object method call
    }

    And, in the VB6 code of the object, here's the pseudo-definition of showThreadIDMessageBox.
    Public Sub showThreadIDMessageBox()
    Call MessageBox(GetCurrentThreadId()) //displays 1, I want it to display 2
    End Sub

    在创建新线程之前,我通过在主线程上进行 CoUninitializing 实现了我想要的。但是为什么会这样呢?如果在我创建新线程之前在主线程上初始化了 COM,也许由于某种原因它必须是......我不希望应用程序稍后崩溃,因为我必须在创建新线程之前调用 CoUninitialize。这是一些伪代码,说明无论哪个线程首先调用 CoInitialize 都会被 STA 对象选中。
    void myMainUIMethod(){
    MessageBox(GetCurrentThreadId()); // displays 1
    CoUninitialize(); // uninitialize COM on the main thread
    CreateThread(&myCOMObjectThreadProc);
    ***i: MessageBox("When you want to initialize COM on main thread, confirm this");
    CoInitialize();
    }
    void myCOMObjectThreadProc(){
    MessageBox(GetCurrentThreadId()); // displays 2
    ***ii: MessageBox("When you want to initialize COM on the new thread, confirm this");
    CoInitialize(NULL);
    myObject = CoCreateInstance(myObjectsCLSID);
    myObjectInterface = myObject->QueryInterface(myObjectInterfaceCLSID);
    myObjectInterface->showThreadIDMessageBox(); // this shows 2 IF ***ii is confirmed before ***i, 1 otherwise
    }

    非常感谢您,
    科尼留

    最佳答案

    看起来您的问题是您的 COM 组件线程模型是 未指定 在注册表项 InprocServer32 .这意味着该对象被视为 STA(单线程单元),但将被加载到 主(或主机)STA ,而不是创建它的 STA。这是第一个调用 CoInitialize 的线程.在调用 CoCreateInstance 的同一 STA 中创建您必须创建 HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{Your CLSID}\InprocServer32@ThreadingModel注册表值并将其设置为 Apartment .

    引用 MSDN (InprocServer32 registry key documentation):

    If ThreadingModel is not present or is not set to a value, the server is loaded into the first apartment that was initialized in the process. This apartment is sometimes referred to as the main single-threaded apartment (STA). If the first STA in a process is initialized by COM, rather than by an explicit call to CoInitialize or CoInitializeEx, it is called the host STA. For example, COM creates a host STA if an in-process server to be loaded requires an STA but there is currently no STA in the process.

    关于multithreading - COM 对象方法不在 CoInitialize-d 并创建对象的线程上执行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/12487282/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com