17

2番目のスレッドがGetMessage()ループで呼び出すアプリケーションがあります。ある時点で、最初のスレッドは、ユーザーがアプリケーションを終了したいことを認識し、2番目のスレッドにアプリケーションを終了する必要があることを通知します。2番目のスレッドがスタックしているGetMessage()ため、プログラムが終了することはありません。タイムアウトのあるメッセージを待つ方法はありますか?私は他のアイデアにもオープンです。

編集:(追加の説明)

2番目のスレッドは、そのコードスニペットを実行します。

while ( !m_quit && GetMessage( &msg, NULL, 0, 0 ) )
{
    TranslateMessage( &msg );
    DispatchMessage( &msg );
}

最初のスレッドはm_quittrueに設定されます。

4

5 に答える 5

21

テストされていませんが、実際にはオブジェクトなしで関数MsgWaitForMultipleObjectsを試すことができます。

MsgWaitForMultipleObjects(0, NULL, FALSE, timeout, QS_ALLINPUT);

ifが戻っWAIT_TIMEOUTた場合はタイムアウトですが、戻った場合はブロックされないことを保証してWAIT_OBJECT_0呼び出すことができます 。GetMessage

ただし、次の点に注意してください。

スレッドがキューをチェックする関数を呼び出した後、メッセージキューに指定されたタイプの未読入力がある場合、MsgWaitForMultipleObjectsは返されません。

したがって、メッセージ関数のいずれかを最後に呼び出したときに、キューにメッセージが残っていないことを確認する必要があります。そうしないと、一種の競合状態になります。

おそらくあなたの最良の選択肢は次のものに置き換えることでしょうGetMessage

if (MsgWaitForMultipleObjects(0, NULL, FALSE, timeout, QS_ALLINPUT) == WAIT_OBJECT_0)
{
    while (PeekMessage(&msg, 0, 0, 0, PM_REMOVE))
    {
        //dispatch the message
    }
}

しかし、前に言ったように、私はそれをテストしなかったので、それが機能するかどうかはわかりません。

于 2012-06-02T22:37:02.890 に答える
19

最も簡単な方法は、を呼び出すUINT_PTR timerId=SetTimer(NULL, NULL, 1000, NULL)前に呼び出すことGetMessageです。WM_TIMER毎秒呼び出しスレッドにメッセージを投稿するので、GetMessageはすぐに戻ります。次に、電話KillTimer(NULL, timerId)してキャンセルします。

UPDATEサンプルコード:

BOOL GetMessageWithTimeout(MSG *msg, UINT to)
{
    BOOL res;
    UINT_PTR timerId = SetTimer(NULL, NULL, to, NULL);
    res = GetMessage(msg);
    KillTimer(NULL, timerId);
    if (!res)
        return FALSE;
    if (msg->message == WM_TIMER && msg->hwnd == NULL && msg->wParam == timerId)
        return FALSE; //TIMEOUT! You could call SetLastError() or something...
    return TRUE;
}
于 2012-06-02T22:11:57.240 に答える
4

常に実行できることの1つは、ブロックされたスレッドにユーザー定義のメッセージを送信することです。これにより、スレッドはウェイクアップし、メッセージを処理してから、ループの先頭に戻ります。実際、m_quit変数を完全に削除し、代わりに「今すぐ終了する必要があります」というメッセージをメインスレッドに送信するのが最も簡単な場合があります。

お役に立てれば!

于 2012-06-02T22:17:29.577 に答える
3

終了メッセージを。を使用して2番目のスレッドに投稿できるはずですPostThreadMessage

例えば

PostThreadMessage(threadid, WM_QUIT, 0, 0);

m_quit2番目のスレッドで変数を読み取る必要はありませんが、からのエラーと、次のメッセージが終了メッセージである場合に返されるGetMessage戻り値を確認する必要があります。FALSE/0

于 2012-06-02T22:33:52.423 に答える
-1

うん。PeekMessage()代わりに試してください。しかし、これは完全な問題解決ではないと思います。

于 2012-06-02T22:10:38.113 に答える