インターフェイス ポインタをスレッドに渡すにはどうすればよいですか?
-
21-08-2019 - |
質問
注記:
- 使用する 生のWin32 CreateTheard() API
- MFCなし
- インターフェイスは単なる vtable へのポインタです
質問:
- インターフェイス ポインタをスレッドに渡すにはどうすればよいですか?
図:
IS8Simulation *pis8 = NULL;
...
CoCreateInstance(
clsid,
NULL,
CLSCTX_LOCAL_SERVER,
__uuidof(IS8Simulation),
(void **) &pis8);
...
hThread = CreateThread(
NULL,
0,
SecondaryThread,
//interface pointer pis8
0,
&dwGenericThreadID);
...
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
//using iValue accordingly
//E.g.: iValue->Open
よろしく
解決
は安全ではないでスレッド間COM
インターフェースポインタを渡す、以下に述べたように
あなたは何をしているかを知っていると仮定します:
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) pis8
0,
&dwGenericThreadID);
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
((IS8Simulation*) iValue)->Open();
}
スレッドセーフ版ます:
void MainThread()
{
IStream* psis8;
HRESULT res = CoMarshalInterThreadInterfaceInStream (IID_IS8SIMULATION, pis8, &psis8);
if (FAILED(res))
return;
hThread = CreateThread(
NULL,
0,
SecondaryThread,
(LPVOID) psis8
0,
&dwGenericThreadID
);
}
DWORD WINAPI SecondaryThread(LPVOID iValue)
{
IS8Simulation* pis8;
HRESULT res = CoGetInterfaceAndReleaseStream((IStream*) iValue, IID_IS8SIMULATION, &pis8);
if (FAILED(res))
return (DWORD) res;
pis8->Open();
}
他のヒント
質問のインターフェイスが COM インターフェイスの場合、Quassnoi が提供するアプローチでは不十分な可能性があります。使用中の COM オブジェクトのスレッド モデルに注意する必要があります。セカンダリ スレッドが、COM オブジェクトが作成されたものとは別の COM アパートメントに参加する場合、およびそのオブジェクトが アパートアジャイル, の場合、セカンダリ スレッドがオブジェクトへの直接ポインタではなくプロキシを取得できるように、そのインターフェイス ポインタをマーシャリングする必要があります。
COM オブジェクトは通常、IMarshal の特別な実装を使用してアパートメント アジャイルに作成されます。最も簡単なアプローチは、フリー スレッド マーシャラーを集約することです。
いくつかの便利なリンク...
アップデート:フリースレッドマーシャラーについて...
このトピックに関するコメントから、FTM には決して触れないことを推奨する人がいることは明らかです。『Effective COM』は優れた本ですが、その推奨事項には解釈の余地があるものもあると思います。項目 33 には「FTM に気をつけろ」と書かれています。「FTM を決して使用しないでください」とは書かれていません。非常に賢明なことに、特にアパートメント アジャイル オブジェクトが他のオブジェクトへの参照を保持している場合、それらはアパートメント アジャイルではない可能性があるため、注意することをお勧めします。実際のアドバイスは次のとおりです。アパートメント アジャイル オブジェクトを構築するときは、俊敏性を実現するために FTM を使用するかどうかにかかわらず、慎重に検討してください。アパートメント アジャイル オブジェクトを構築できると確信しているのであれば、それを実現するために FTM を使用しない理由はありません。
基本的には次のことを行う必要があります。
CoMashalInterThreadInterfaceInStream
==> IStream インターフェイスが得られます。- その IStream をスレッドに渡します。カスノイさんの言う通り。
- セカンダリスレッドで呼び出します
CoGetInterfaceAndReleaseStream
インターフェイス (または必要に応じてそのプロキシ) を取得します。
スレッドの作成が失敗しない限り、IStream インターフェイスを解放しないでください。また、呼び出しが完了するまでスレッドを終了しないでください。 CoGetInterfaceAndReleaseStream
.
COM ランタイムはプロキシを自動的に作成します。プロキシは次のことを保証します。アパートメント スレッドの COM コンポーネントは、それを作成したスレッドで呼び出されます。ただし、これには次のことも必要です。
- インターフェイスが IDispatch であるか、インターフェイスにプロキシ/スタブ コンポーネントが登録されています
- コンポーネントを作成したスレッドにはメッセージ ループがあり、メッセージを処理します。