4

スレッドAがWaitForSingleObjectを使用してスレッドBが終了するまで待機しているのではなく、別のスレッドBを作成しているスレッドAがあります。

問題は、スレッドBがスレッドの「thread_func」から戻っても、スレッドAが通知されないことです。

thread_func(スレッドBのメイン関数)の最後にトレース(OutputDebugString)を追加し、スレッドBが実行を終了したことがわかりますが、スレッドAがWaitForSingleObjectから出ることはありません。

ここで、このコードがCOMオブジェクトにあることも追加する必要があります。また、上記のシナリオは、zippy32.exeを呼び出しているときに発生しているため(スタックします!)、スレッドAはDLLMainから来ていると思います。

スレッドAが通知されない理由はありますか?!?!

4

2 に答える 2

14

ローダーロックに問題がある可能性があります。Windows には、DLL のロード/アンロード時、またはスレッドの開始/停止時にロックされる内部クリティカル セクションがあります (DllMain は常にそのロック内で呼び出されます)。待機中のスレッド A がそのクリティカル セクションをロックしている場合 (つまり、DllMain のどこかで待機している場合)、別のスレッド B がシャットダウンを試み、そのローダー クリティカル セクションを取得しようとすると、デッドロックが発生します。

デッドロックが発生した場所を確認するには、VS IDE デバッガーからアプリを実行し、スタックした後に実行を中断します。次に、実行中のすべてのスレッドを調べて、各スレッドのスタックを記録します。各スタックをたどって、各スレッドが何を待っているかを確認できるはずです。

于 2011-07-24T19:18:53.953 に答える
4

@DXMは正しいと思います。内部で実行できることと実行できないことに関するドキュメントDllMainはまばらで見つけるのが難しいですが、肝心なのは、一般的にそれを最小限に抑える必要があるということです-内部変数などを初期化しますが、それだけです。

私が言いたいもう1つのポイントは、通常、zippy32.exeを「呼び出す」べきではないということです。

RegSvr32は基本的に、DLLをアドレス空間にロードする単なるラッパーです。Callsを使用してLoadLibraryGetProcAddressという名前の関数のアドレスを取得し、DllRegisterServerその関数を呼び出します。次のように、自分で仕事をする方がはるかにクリーンです(そして最終的には簡単です)。

HMODULE mod = LoadLibrary(your_COM_file); 
register_DLL = GetProcAddress(mod, "DllRegisterServer"); 
if ( register_DLL == NULL) { 
        // must not really be a COM object... 
} 

if ( S_OK != register_DLL()) { 
        // registration failed. 
} 
于 2011-07-24T19:47:09.543 に答える