我正在开发一个 UI 应用程序,它会一路创建一个 COM 对象。
问题是,我想将这个 COM 对象完全“移动”到另一个线程上。
我要做的是:
问题是,正如此消息框所示,对象方法仍然在原始 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/