2012-06-02 3 views
15

두 번째 스레드가 루프로 GetMessage()을 호출하는 응용 프로그램이 있습니다. 어떤 시점에서 첫 번째 스레드는 사용자가 응용 프로그램을 종료하고 종료해야하는 두 번째 스레드에 알리고 있음을 알게됩니다. 두 번째 스레드가 GetMessage()에 고정되어 있으므로 프로그램이 종료되지 않습니다. 타임 아웃이있는 메시지를 기다리는 방법이 있습니까? 다른 아이디어도 열려 있습니다.타임 아웃이있는 GetMessage

는 편집 :

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

첫 번째 스레드가 true로 m_quit을 설정 (추가 설명)는

두 번째 스레드가 코드의 조각을 실행합니다.

+0

대기 ... 어떤 스레드가 'GetMessage()'에서 대기중인 루프에 있습니까? 첫 번째 스레드, 두 번째 스레드 또는 둘 다? – templatetypedef

+0

두 번째 스레드는 GetMessage 루프를 실행합니다. 일부 코드를 게시해야합니까? – qdii

+0

코드가 항상 도움이됩니다. 귀하의 질문에 두 스레드가 차단 된 것처럼 보이기 때문에 나는 혼란스러워합니다. "지금 종료해야합니까?"라는 맞춤 메시지를 보낼 수는 없습니까? – templatetypedef

답변

13

가장 쉬운 방법은 GetMessage을 호출하기 전에 UINT_PTR timerId=SetTimer(NULL, NULL, 1000, NULL)으로 전화하는 것입니다. 매 초마다 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()'를 호출하는 것이 좋은 해결책이 될 것이지만, 제 경우에는 두 번째 스레드가 매우 민감해야합니다. +1은 솔루션이 다른 상황에서 유효하기 때문에 – qdii

4

한 가지 당신은 항상 그냥 차단 된 스레드에게이 일어나 발생합니다 사용자 정의 메시지, 프로세스 메시지를 전송 할 수있는, 다음 백업 이동 루프 상단으로 이동합니다. 실제로 m_quit 변수를 완전히 제거하고 주 스레드에 "지금 종료해야합니다."라는 메시지를 보내는 것이 가장 쉽습니다.

희망이 도움이됩니다.

+1

+1, 도움이됩니다. Rodrigo의 솔루션을 선호하는 이유는 전체 종료 메커니즘을 한 곳에서 유지하기 때문입니다. – qdii

+1

이것은 훨씬 깨끗한 방법입니다. 스레드의 요점은 무엇을해야하는지 알려주는 메시지를받는 것입니다. 그리고 이것은 아무 것도 할 필요가 없을 때 실이 끊임없이 깨어날 필요가 없습니다. –

2

PostThreadMessage으로 두 번째 스레드에 종료 메시지를 게시 할 수 있어야합니다.

예.

PostThreadMessage(threadid, WM_QUIT, 0, 0); 

당신은 두 번째 스레드에서 m_quit 변수를 읽을 필요가 없습니다하지만 다음 메시지가 종료 메시지가 있다면 당신은 GetMessage뿐만 아니라 반환되는 것입니다 FALSE/0의 반환 값에서 오류를 검사한다 .

18

테스트하지 않았지만 실제적으로 어떤 객체도없이 MsgWaitForMultipleObjects 함수를 사용해 볼 수 있습니다.

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

반환 WAIT_TIMEOUT가 타임 아웃이지만 WAIT_OBJECT_0를 반환하는 경우 보증에 GetMessage하지 차단하기 위해 호출 할 수 있으면합니다.

그러나 다음과 같은주의 : 스레드가 큐를 확인하는 함수를 호출 한 후 메시지 큐에 지정된 유형의 읽지 않은 입력이있을 경우 반환하지 않습니다

MsgWaitForMultipleObjects를.

마지막으로 메시지 기능을 호출 할 때 대기열에 남아있는 메시지가 없거나 일종의 경쟁 조건이 있어야합니다.

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

을하지만 내가 전에 말했듯이, 나는 그렇게 나는 그것이 작동하는지 확신 할 수 없다 테스트하지 않았다

아마 당신의 최선의 선택은 함께 GetMessage을 대체하는 것입니다.

+1

아 그게 더 좋은 이벤트 야. – qdii

+8

나는이 루틴으로 ** SendMessage ** 메시지를 기다리는 교착 상태가 발생했다. ** 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

관련 문제