2016-06-22 13 views
1

私のMFCアプリケーションでは、ネットワーク接続をリッスンするワーカースレッドがあり、情報が到着するとすぐにSendMessageToDescendantsにlparamパラメータを介して情報を送信するように呼び出します。したがって、すべてのフレームウィンドウはメッセージを取得し、可能であればWM_SYNCHRONOTIFICATIONメッセージ(WM_SYNCHRONOTIFICATIONWM_APP+xメッセージ)のメッセージハンドラを介して処理します。ワーカースレッドでスレッド間でSendMessageToDescendantsを使用する

コード:メインスレッドで

while (TRUE) 
{ 
    CNotificationMessage notificationmessage; 
    Listen(&notificationmessage); // blocking until some information arrives 

    m_pMainWnd->SendMessageToDescendants(WM_SYNCHRONOTIFICATION, NULL, (LPARAM)(newnotif)); 

    // have all OnSynchroNotification handlers been called here ? 
} 

メッセージハンドラ(簡潔にするために簡略化):

LRESULT CMyFrame::OnSynchroNotification(WPARAM p1, LPARAM p2) 
{ 
    CNotificationMessage *pNotification = (CNotificationMessage*)p2; 

    // process message (ommited for brevity) 
} 

コードが正常に動作しますが、私はありませんよ戻り時にSendMessageToDescendantsからすべてOnSynchroNotificationが呼び出されているかどうかを確認してください。

+4

[どんなのSendMessage品種を使用しないでくださいスレッドから](http://stackoverflow.com/a/29603742/17034)。 –

答えて

2

最も簡単な解決策は、カウンターです。 SendMessageを呼び出す前に、メッセージを処理したい子ウィンドウの数に共有カウンタを初期化します。各メッセージハンドラは、作業が完了したときにカウンタの値を減らす役割を果たします。さらにイベントを生成する前にカウンタが0であることをイベントループで確認できます。擬似C++では:その後、

unsigned int sharedCount; // global/static shared value 

while (TRUE) 
{ 
    CNotificationMessage notificationmessage; 
    Listen(&notificationmessage); // blocking until some information arrives 

    unsigned int current = InterlockedCompareExchange(&sharedCount, activeWindowCount, 0); 
    if (current == 0) 
    { 
     m_pMainWnd->SendMessageToDescendants(WM_SYNCHRONOTIFICATION, NULL, (LPARAM)(newnotif)); 
    } 
    else 
    { 
     // Still processing the last message. 
    } 

    while (InterlockedCompareExchange(&sharedCount, 0, 0) != 0) 
    { 
     Sleep(100); 
    } 
} 

LRESULT CMyFrame::OnSynchroNotification(WPARAM p1, LPARAM p2) 
{ 
    // Processing 
    InterlockedDecrement(&sharedCount); 
} 

もう少し複雑なソリューションが、私は個人的に好む1、あなたは完了を待っているCPUを燃焼させる必要がないため、各メッセージの処理ウィンドウのためのイベントを作成することであり、 WaitForMultipleObjects(またはExバージョン)を使用して、完了するまでイベントループを停止します。ここでも、擬似C++で:

while (TRUE) 
{ 
    CNotificationMessage notificationmessage; 
    Listen(&notificationmessage); // blocking until some information arrives 

    m_pMainWnd->SendMessageToDescendants(WM_SYNCHRONOTIFICATION, NULL, (LPARAM)(newnotif)); 

    DWORD waitResult = WaitForMultipleObjects(activeWindowCount, FrameEvents, TRUE, INFINITE); 
    if (waitResult == WAIT_OBJECT_0) 
    { 
     // Success 
    } 
    else if (waitResult == WAIT_FAILED) 
    { 
     // Failure: Use GetLastError() to figure out why the function call failed. 
    } 

    // Reset the events 
}  

LRESULT CMyFrame::OnSynchroNotification(WPARAM p1, LPARAM p2) 
{ 
    // Processing 
    SetEvent(thisFramesEvent); 
} 

この例では、無限のタイムアウトを使用しますが、あなたは常に合理的なタイムアウトを設定し、時間が経過したかどうかを確認するために、戻り値WAIT_TIMEOUTをチェックすることができます。

(必須免責事項:エラーチェックや変数の初期化は、簡潔さと読みやすさのためにこれらの両方から削除されたエラーをチェックする方法については、マニュアルを参照してください。。)

関連する問題