在线程

时间:2016-06-22 09:52:21

标签: multithreading winapi mfc

在我的MFC应用程序中,我有一个侦听网络连接的工作线程,一旦有一些信息到达,我调用SendMessageToDescendants通过lparam参数发送该信息。因此,每个框架窗口都将获取消息,并可能通过消息处理程序处理WM_SYNCHRONOTIFICATION消息(WM_SYNCHRONOTIFICATIONWM_APP+x消息)。

工作线程中的代码:(为简洁而简化)

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后是否已被调用。

1 个答案:

答案 0 :(得分: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);
}

稍微复杂的解决方案,但我个人更喜欢的解决方案,因为您不必在完成时刻录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以查看时间是否已过去。

(必需免责声明:为了简洁起见和可读性,已从这两个版本中删除了错误检查和变量初始化。请参阅文档以了解如何检查错误。)