无法删除WM_TIMER消息

时间:2016-04-15 16:03:07

标签: c++ windows winapi timer

我的代码有问题,几个小时后,我似乎无法弄明白......

问题:我试图每十秒尝试连接一台服务器。当计时器第一次过去时,回调函数被调用就好了,但随后立即再次调用它(不等待十秒),并且一次又一次地反复调用它,好像定时器消息没有从中移除队列。有人可以帮忙吗?

计时器在此处设置:

SConnect::SConnect()
{
    hSimConnect = NULL;
    Attempt();
    SetTimer(hMainWindow, reinterpret_cast<UINT_PTR>(this), 10000, (TIMERPROC)TimerProc);
}

(仅)应用程序消息循环在此处:

    while (true)
    {
        PeekMessage(&msg, NULL, 0, 0, PM_REMOVE);
        if (msg.message == WM_QUIT)
            break;

        if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
        {
            TranslateMessage(&msg);
            DispatchMessage(&msg);
        }

        //UPDATES
        pSCObj->Update();
        manager.Update();
        Sleep(50);
    }

定时器回调函数在这里:

void CALLBACK SConnect::TimerProc(HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime){
    SConnect *pSC = reinterpret_cast<SConnect *>(idEvent);
    MSG wMsg;

    if (!pSC->connected)
    pSC->Attempt();
    else{
        pSC->connected = false;
    }
}

我真的很感激任何帮助......如果您需要更多信息,请告诉我......

此致 法利

2 个答案:

答案 0 :(得分:2)

我认为这种情况正在发生,因为您在消息循环中调用了PeekMessage()而不是GetMessage()

如果队列中没有消息,

PeekMessage()将返回FALSE。我不知道PeekMessage()的实现是什么,但如果队列中没有消息,我可以看到它只留下msg参数的内容。这意味着当PeekMessage()返回FALSE时,msg将包含队列中的上一条消息。然后将msg盲目传递给DispatchMessage(),然后尽职地将其传递到您窗口的窗口程序。因此,只要WM_TIMER消息是最后处理的消息,就会调用您的计时器回调,直到将另一条消息添加到队列中。

您可以使用更传统的消息循环来解决此问题:

BOOL bRet;

while( (bRet = GetMessage( &msg, nullptr, 0, 0 )) != 0)
{ 
    if (bRet == -1)
    {
        // handle the error and possibly exit
    }
    else
    {
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    }

    pSCObj->Update();
    manager.Update();
}

(消息循环改编自GetMessage()文档中的示例。)

由于GetMessage()将阻塞,直到队列中有消息,您不需要调用Sleep(),并且当没有任何内容时,您的进程将不会使用任何CPU做。

答案 1 :(得分:1)

问题是未检查PeekMessage()的返回值。在每个循环中,如果没有新消息,PeekMessage将保留msg的内容不变,并且只是再次调度它。

仅当PeekMessage()返回true时调度消息才能解决问题:

    while (true)
    {
        if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)){
            if (msg.message == WM_QUIT)
                break;    

            if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
        }

        //UPDATES
        pSCObj->Update();
        manager.Update();
        Sleep(50);
    }