Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/161.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ Can';t删除WM_定时器消息_C++_Windows_Winapi_Timer - Fatal编程技术网

C++ Can';t删除WM_定时器消息

C++ Can';t删除WM_定时器消息,c++,windows,winapi,timer,C++,Windows,Winapi,Timer,我的代码有问题,几个小时后,我似乎无法理解 问题:我正在尝试每10秒连接一个服务器。当计时器第一次过期时,回调函数会被很好地调用,但随后会立即再次调用它(无需等待10秒),并且它会被一次又一次地重复调用,就好像计时器消息没有从队列中删除一样。有人能帮忙吗 计时器在此处设置: SConnect::SConnect() { hSimConnect = NULL; Attempt(); SetTimer(hMainWindow, reinterpret_cast<UINT

我的代码有问题,几个小时后,我似乎无法理解

问题:我正在尝试每10秒连接一个服务器。当计时器第一次过期时,回调函数会被很好地调用,但随后会立即再次调用它(无需等待10秒),并且它会被一次又一次地重复调用,就好像计时器消息没有从队列中删除一样。有人能帮忙吗

计时器在此处设置:

SConnect::SConnect()
{
    hSimConnect = NULL;
    Attempt();
    SetTimer(hMainWindow, reinterpret_cast<UINT_PTR>(this), 10000, (TIMERPROC)TimerProc);
}
计时器回调函数如下所示:

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;
    }
}
void CALLBACK SConnect::TimerProc(HWND HWND、UINT uMsg、UINT_PTR idEvent、DWORD dwTime){
SCONECT*pSC=重新解释铸件(idEvent);
MSG-wMsg;
如果(!pSC->已连接)
pSC->trunt();
否则{
pSC->connected=false;
}
}
我真的很感激任何帮助。。。请让我知道如果你需要更多的信息

真诚地,
Farley

我认为这是因为您在消息循环中调用的是
peek message()
,而不是
GetMessage()

如果队列中没有消息,
peek message()
将返回
FALSE
。我不知道
peek message()
的实现是什么,但是如果队列中没有消息,我可以看到它将
msg
参数的内容单独保留。这意味着当
peek message()
返回
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()
将一直阻塞,直到队列中有消息,因此您不需要调用
Sleep()
,并且当没有什么事情可做时,您的进程将不会使用任何CPU。

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

如果队列中没有消息,
peek message()
将返回
FALSE
。我不知道
peek message()
的实现是什么,但是如果队列中没有消息,我可以看到它将
msg
参数的内容单独保留。这意味着当
peek message()
返回
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()
将一直阻塞,直到队列中有消息为止,因此您不需要调用
Sleep()
,并且当没有任何事情可做时,您的进程将不会使用任何CPU。

问题是没有检查peek message()的返回值。在每个循环中,如果没有新消息,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);
    }

问题是没有检查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);
    }

这些计时器是周期性的。你必须打电话给KillTimer()让他们停止。哦,对不起,我的问题不清楚。我的意思是回调会立即一次又一次地被调用(不是每十秒钟一次)。请提供一个,从而避免任何混淆的范围。如果消息循环中存在大量错误,它不会检查PeekMessage()的返回值。因此,您得到的第一个WM_计时器将工作。然后PeekMessage()返回FALSE,这是您看不到的,您将一次又一次地发送消息。Sleep(50)调用也是非常邪恶的。顺便说一句,
Sleep()
意味着您的程序每秒最多处理20条消息。这也意味着对任何新消息的响应都需要50毫秒。您不应该在UI线程上睡眠。如果你想每50ms更新一次,那么创建另一个计时器来触发更新。这些计时器是周期性的。你必须打电话给KillTimer()让他们停止。哦,对不起,我的问题不清楚。我的意思是回调会立即一次又一次地被调用(不是每十秒钟一次)。请提供一个,从而避免任何混淆的范围。如果消息循环中存在大量错误,它不会检查PeekMessage()的返回值。因此,您得到的第一个WM_计时器将工作。然后PeekMessage()返回FALSE,这是您看不到的,您将一次又一次地发送消息。Sleep(50)调用也是非常邪恶的。顺便说一句,
Sleep()
意味着您的程序每秒最多处理20条消息。这也意味着对任何新消息的响应都需要50毫秒。您不应该在UI线程上睡眠。如果你想每50毫秒更新一次,那么再创建一个计时器来触发更新。我在所有程序中都使用相同的消息循环,所以我不再关注它:)不过
Sleep(50)
应该是一个很好的警告+1要记住这不是一个函数替换,Update()方法的调用远远不够