我正在开发一个 UI 应用程序,它会一路创建一个 COM 对象。问题是,我想将这个 COM 对象完全“移动”到另一个线程上。
我要做的是:
- 创建我想将对象移动到的新线程(使用 CreateThread API)
- 进入此线程后,我正在调用 PeekMessage 为其设置消息队列
- 调用CoInitialize,CoCreateInstance创建COM对象,QueryInterface得到我想要的接口
- 最后,我在界面上调用一个方法,该方法显示一个带有 GetCurrentThreadId() 返回值的 MessageBox(我可以访问该对象所在的 COM 库的 VB6 代码)。
问题是,正如此消息框所示,对象方法仍然在原始 UI 线程上执行,而不是在我创建并完成所有这些步骤的线程上执行。还要提一提,在调用了接口方法之后,我还在里面设置了一个经典的消息循环。
我怎样才能改变这种行为并实现我想要的?(也就是说,我希望源自我新创建的线程的 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
}
非常感谢你,科内利乌