途中でCOMオブジェクトを作成するUIアプリケーションを開発しています。問題は、このCOMオブジェクトを完全に別のスレッドに「移動」したいということです。
私がしていることはこれです:
- オブジェクトを移動したい新しいスレッドを作成します(CreateThread APIを使用)
- このスレッドに入った後、PeekMessageを呼び出してメッセージキューを設定します
- CoInitialize、CoCreateInstanceを呼び出してCOMオブジェクトを作成し、QueryInterfaceを呼び出して必要なインターフェイスを取得します
- 最後に、GetCurrentThreadId()によって返された値を使用してMessageBoxを表示するインターフェイスのメソッドを呼び出します(オブジェクトが存在するCOMライブラリのVB6コードにアクセスできます)。
問題は、このメッセージボックスに示されているように、オブジェクトメソッドは、作成してこれらすべての手順を実行したスレッドではなく、元のUIスレッドで実行されることです。もう1つ言及すべきことは、インターフェイスメソッドを呼び出した後、クラシックメッセージループも設定していることです。
この動作を変更して、目的を達成するにはどうすればよいですか?(つまり、新しく作成したスレッドから発信された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
新しいスレッドを作成する前に、メインスレッドで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
}
よろしくお願いします、Corneliu