2012-06-02 51 views
15

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

はEDIT:

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

最初のスレッドがtrueにm_quitを設定:(追加説明が)

第二のスレッドがコードのスニペットを実行します。

+0

Wait ...どのスレッドが 'GetMessage()'を待ってループしていますか?最初のスレッド、2番目のスレッド、またはその両方? – templatetypedef

+0

2番目のスレッドはGetMessageループを実行します。私はいくつかのコードを投稿する必要がありますか? – qdii

+0

コードは常に役立ちます。あなたの質問は、両方のスレッドがブロックされているように思えるので、私はちょうど混乱しています。 「今すぐシャットダウンする必要がある」というカスタムメッセージを送信できませんか? – templatetypedef

答えて

13

最も簡単な方法は、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; 
} 
+0

ちょっと変わったウォッチドッグ=) – Forgottn

+0

@rodrigo:+1。これまで私が見てきた最高の解決策です。私は他の候補者が現れるのを待つでしょう。 – qdii

+0

@rodrigo 'msg'は、ポインタです。また、指し示された構造体は 'uMsg'メンバを持たず、' message'と呼ばれます。 – qdii

-1

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

+0

@Forgoth私は 'Sleep(1000)'と組み合わせることができれば 'PeekMessage()'を呼び出すのが良い方法ですが、私の場合は2番目のスレッドは非常に反応がよくなければなりません。 +1は解決が他の文脈で有効であるので – qdii

4

あなたは常に行うことができますことの一つは、ちょうどそのアップ戻って、プロセスメッセージ、ブロックされたスレッドにそれが目を覚ますようになります、ユーザー定義のメッセージを送っていますループの先頭に移動します。実際には、変数m_quitを完全に削除し、メインスレッドに「今すぐ終了する必要があります」というメッセージを送信する方が簡単な場合があります。

希望すると便利です。

+1

+1これは役に立ちます。私はロッドジーゴの解を好むのは、停止機構全体を1か所に保持するからです。 – qdii

+1

これははるかにクリーンな方法です。スレッドのポイントは、何をすべきかを伝えるメッセージを受け取ることです。そして、これは、スレッドが何もしなくても常に起きる必要はありません。 –

2

PostThreadMessageで2番目のスレッドに終了メッセージを投稿することができます。

など。あなたが第二のスレッドでm_quit変数を読んでする必要はありませんが、あなたがGetMessageだけでなく、次のメッセージが終了メッセージである場合に返されるものですFALSE/0の戻り値からエラーをチェックする必要があり

PostThreadMessage(threadid, WM_QUIT, 0, 0); 

18

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

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

リターンがWAIT_TIMEOUTそれがタイムアウトであるが、それはWAIT_OBJECT_0を返す場合、あなたはブロックされないように保証してGetMessageを呼び出すことができる場合であれば。

しかし、次の点に注意してください。スレッドはキューをチェックする関数を呼び出した後に、指定されたタイプの未読入力がメッセージキューに存在する場合

MsgWaitForMultipleObjectsは戻りません。

メッセージ機能を最後に呼び出したときにメッセージがキューに残っていないこと、または競合状態が発生していることを確認する必要があります。

おそらくあなたの最良のオプションはでGetMessageを置き換えるために、次のようになります。

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

しかし、私が前に言ったように私はそれが動作するかどう確認することはできませんので、私はそれをテストしていません。

+1

ああ、これはイベントのほうがいいよ – qdii

+8

このルーチンで** SendMessage ** msgを待っているデッドロックがあった。 ** QS_ALLLEVENTS **の代わりに** QS_ALLINPUT **を使用する必要があります。これは** QS_SENDMESSAGE **にも適用されるためです。詳細については[msdn](http://msdn.microsoft.com/en-us/library/windows/desktop/ms684242%28v=vs.85%29.aspx)を参照してください – 5andr0

+0

ありがとう@ 5andr0 'QS_ALLINPUT'は何でしたか私のためにそれを固定! – Noitidart

関連する問題