我的代码出了问题,几个小时后,我似乎想不出.
问题:我试图每十秒钟连接一台服务器。当计时器第一次过去时,回调函数被调用得很好,但是它会立即被一次又一次地调用(不需要等待10秒),并且会一次又一次地被调用,就好像计时器消息没有从队列中移除一样。有人能帮忙吗?
定时器设置在这里:
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;
}
}我真的很感激任何帮助..。如果你需要更多信息请告诉我..。
真的,法利
发布于 2016-04-15 16:32:22
我认为这是因为您在消息循环中调用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。
发布于 2016-04-15 21:20:06
问题是没有检查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);
}https://stackoverflow.com/questions/36651902
复制相似问题