Cor*_*uzu 4 com methods multithreading invoke
我正在开发一个UI应用程序,在此过程中创建一个COM对象.问题是,我想完全在另一个线程上"移动"这个COM对象.
我这样做是:
问题是,正如此消息框所示,对象方法仍然在原始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
Run Code Online (Sandbox Code Playgroud)
在创建新线程之前,我已经通过CoUninitalizing在主线程上实现了我想要的.但为什么会这样呢?如果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
}
Run Code Online (Sandbox Code Playgroud)
非常感谢,Corneliu
看起来您的问题是您的COM组件线程模型未在注册表项InprocServer32中指定.这意味着该对象被视为STA(单线程单元),但将被加载到主(或主机)STA,而不是创建它的STA.这是第一个调用的线程CoInitialize.要在调用CoCreateInstance您的同一STA中创建,必须创建HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{Your CLSID}\InprocServer32@ThreadingModel注册表值并将其设置为Apartment.
从MSDN引用(InprocServer32注册表项文档):
如果ThreadingModel不存在或未设置为值,则服务器将加载到在该过程中初始化的第一个公寓中.这间公寓有时被称为主要的单线程公寓(STA).如果进程中的第一个STA由COM初始化,而不是通过显式调用CoInitialize或CoInitializeEx,则称为主机STA.例如,如果要加载的进程内服务器需要STA但是进程中当前没有STA,则COM会创建主机STA.
| 归档时间: |
|
| 查看次数: |
4394 次 |
| 最近记录: |