2

私は mdi を使用するアプリケーションを使用しており、スクリプトを mdi ウィンドウにアタッチしたり、mdi ウィンドウから切り離したりして、オンデマンドで実行/停止することができます。このスクリプトは、何らかの作業を行う dll をロードします。それはうまくいきます。ただし、スクリプトをデタッチしてもすべて問題なく、アプリケーションは dll をアンロードする必要があります (適切な thread_attach/detach および process_attach/detach 操作で dllmain を呼び出します)。スクリプトをウィンドウに再アタッチしようとしたり、別のウィンドウにアタッチしようとすると、dll が一度使用された後、メイン アプリケーションがクラッシュします。dll によって作成されたスレッドに問題を特定しました。トレッドは窓を作ります。だから、私は次のようにスレッドを作成します:

if (!hThread) hThread = CreateThread(NULL, 0, ThreadProc, NULL, 0, NULL);

そして、スクリプトがデタッチされると、次のようにスレッドをシャットダウンします (コメントアウトされた行がコメントアウトされていなくても):

SendMessage(hWnd, WM_DESTROY, 0, 0);
//TerminateThread(hThread, 0);
//WaitForSingleObject(hWndThread, INFINITE);
CloseHandle(hThread);
hThread = NULL;

メインアプリがクラッシュする理由について、ここで途方に暮れています。別のスレッド (つまり、単純に 1 秒間スリープしてループするスレッド) は、害を及ぼすことはありません。

4

1 に答える 1

0

わかりました、ここにいくつかのアイデアがあります: あなたのスレッドはウィンドウを開くと言いました。スレッド関数でメッセージ ループを実行していますか、それともウィンドウが他のメッセージ ループによって処理されることを期待していますか? スレッドで独自のメッセージ ループを実行している場合、記述方法によっては、ループを終了する場合としない場合があります。次のようなものを使用する場合:

while(GetMessage(&msg, ...) // msg loop in the thread function
{
  .... 
}
DestroyWindow(hWnd);  // see comment below

その場合、終了するには WM_DESTROY ではなく WM_QUIT が必要です。とにかく、ウィンドウに WM_QUIT を送信し、メッセージ ループを終了した後、DestroyWindow() を呼び出して適切に破棄するのが最善です。MSDN からの引用:

DestroyWindow 関数 指定されたウィンドウを破棄します。この関数は、WM_DESTROY および WM_NCDESTROY メッセージをウィンドウに送信して非アクティブ化し、キーボード フォーカスをウィンドウから削除します。この関数は、ウィンドウのメニューを破棄し、スレッド メッセージ キューをフラッシュし、タイマーを破棄し、クリップボードの所有権を削除し、クリップボード ビューアー チェーンを中断します (ウィンドウがビューアー チェーンの最上位にある場合)。

WM_QUIT メッセージをウィンドウに送信した後、メイン スレッドはウィンドウ スレッドが終了するまで待機する必要があります。関連するコードを次に示します。

SendMessage(hWnd, WM_QUIT, 0, 0);  // send your quit message to exit the msg loop
if (WaitForSingleObject(hThread, 5000) != WAIT_OBJECT_0) // wait up to 5 seconds
{
    TerminateThread(hThread, -1); // bad! try to never end here
}

これが役立つことを願っています。これは、ウィンドウを使用してログ メッセージを表示するスレッド化されたログ ビューアで使用します。

于 2013-01-18T22:20:53.490 に答える