在我的MFC应用程序中,我有一个侦听网络连接的工作线程,一旦有一些信息到达,我调用SendMessageToDescendants
通过lparam参数发送该信息。因此,每个框架窗口都将获取消息,并可能通过消息处理程序处理WM_SYNCHRONOTIFICATION
消息(WM_SYNCHRONOTIFICATION
是WM_APP+x
消息)。
工作线程中的代码:(为简洁而简化)
while (TRUE)
{
CNotificationMessage notificationmessage;
Listen(¬ificationmessage); // 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
后是否已被调用。
答案 0 :(得分:2)
最简单的解决方案是使用计数器。在调用SendMessage
之前,将共享计数器初始化为您希望处理该消息的子窗口数。然后,每个消息处理程序负责在计数器完成其工作时递减计数器,并且您的事件循环可以在生成更多事件之前检查计数器是否为0。在伪C ++中:
unsigned int sharedCount; // global/static shared value
while (TRUE)
{
CNotificationMessage notificationmessage;
Listen(¬ificationmessage); // 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);
}
稍微复杂的解决方案,但我个人更喜欢的解决方案,因为您不必在完成时刻录CPU等待,就是为每个消息处理窗口创建一个事件,然后使用WaitForMultipleObjects
(或Ex版本)停止事件循环直到完成。再次,在伪C ++中:
while (TRUE)
{
CNotificationMessage notificationmessage;
Listen(¬ificationmessage); // 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
以查看时间是否已过去。
(必需免责声明:为了简洁起见和可读性,已从这两个版本中删除了错误检查和变量初始化。请参阅文档以了解如何检查错误。)