为啥我的应用程序最小化时 CPU 使用率会增加?

Posted

技术标签:

【中文标题】为啥我的应用程序最小化时 CPU 使用率会增加?【英文标题】:Why does CPU usage increase when my application is minimized?为什么我的应用程序最小化时 CPU 使用率会增加? 【发布时间】:2011-06-30 07:16:50 【问题描述】:

我正在编写一个计算器。窗口最大化时,CPU 使用率约为 12%,但最小化时,CPU 使用率上升到 50% 左右。为什么会发生这种情况,我该如何防止这种情况发生?这是我认为导致问题的一段代码。

LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)

switch(uMsg)

case WM_ACTIVATE:
    if(!HIWORD(wParam))
        active = true;
    else
        active = false;

    return 0;

case WM_SYSCOMMAND:
    switch(wParam)
    
    case SC_SCREENSAVE:
    case SC_MONITORPOWER:
        return 0;
    
    break;

case WM_CLOSE:
    PostQuitMessage(0);
    return 0;

case WM_KEYDOWN:
    if( (wParam >= VK_LEFT && wParam <= VK_DOWN) || wParam == VK_CONTROL)
        myCalc.handleInput(wParam, true);
    return 0;

case WM_CHAR:
    myCalc.handleInput(wParam);
    return 0;

case WM_SIZE:
    ReSizeGLScene(LOWORD(lParam), HIWORD(lParam));  //LOWORD = Width; HIWORD = Height
    return 0;


return DefWindowProc(hWnd, uMsg, wParam, lParam);


int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int     nShowCmd)

MSG msg;

if(!CreateGLWindow(WINDOW_CAPTION, WINDOW_WIDTH, WINDOW_HEIGHT, WINDOW_BPP))

    return 0;


while(!done)    //Main loop

    if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
    
        if(msg.message == WM_QUIT)
            done = true;
        else
        
            TranslateMessage(&msg); //Translate the message
            DispatchMessage(&msg);  //Dispatch the message
        
    
    else
    
        //Start the time handler
        myTimeHandler.Start();

        //Draw the GL Scene
        if(active)
        

            DrawGLScene();      //Draw the scene
            SwapBuffers(hDC);   //Swap buffer (double buffering)
        

        //Regulate the fps
        myTimeHandler.RegulateFps();
    


//Shutdown
KillGLWindow();
return(msg.wParam);

【问题讨论】:

【参考方案1】:

我的猜测是,如果active 为假,您的主循环将毫无延迟地运行。线程在该循环中无限旋转,并使您的两个处理器内核中的一个保持忙碌(这就是您看到 50% 的 CPU 负载的原因)。

如果active 为真,则交换操作会等待下一次垂直同步并延迟循环,直到下一次屏幕刷新发生,从而降低 CPU 负载。 (线程在 Windows 函数中等待事件发生的时间不计入其 CPU 负载。)

要解决该问题,您可以在不想渲染任何内容时切换到基于GetMessage 的消息循环。

【讨论】:

【参考方案2】:

您的 OpenGL 窗口覆盖的区域越少,绘制场景的速度就越快(关键术语是 fillrate),因此事件循环的迭代频率越高。我看到你有一些函数RegulateFps - 对我来说,这听起来像是一个繁忙的循环,直到渲染器消耗了一定的时间。 IE。您实际上是在浪费 CPU 时间来获得……呃,为什么您首先要保持低帧率?摆脱它。

当然,如果你把它最小化,你设置active = false 所以根本不做 GL 的事情,但仍然在繁忙的循环中浪费时间。

尝试在驱动选项中打开垂直同步,并使用双缓冲,然后wglSwapBuffers 将阻塞直到垂直空白。如果active==false 不是PeekMessage 而是GetMessage

【讨论】:

【参考方案3】:

好的。我看到了你的逻辑流程之一。

while(!done) //Main loop if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) ...... else .... rendering.

当你最小化时,peekMessage总是会失败,所以你会来渲染部分。

这会导致你使用 100% 单核 cpu,因为它处于 while 循环并且从不休眠,等待,只是一遍又一遍地绘制。

您可能希望为渲染帧设置最短时间。

我的建议是:

// set a timer for wakeup ur process. while (::GetMessage(&msg, NULL, 0, 0)) // handle the messages // do check the rendering to see if you need to render. if (currentTime - lastDrawTime > MINIMIUM_RENDER_INTERVAL) // rendering.

【讨论】:

PeekMessage 总是立即返回,而几乎总是返回false,不管窗口是最小化还是最大化。 这取决于,如果你有很多消息要处理,我相信它不会返回 false。在那种情况下,你永远不会来渲染。 (虽然它不会在现实世界中发生)。还有一点是:空闲的时候你总会画画。假设如果您有一些缓慢的 msg 处理过程,您的框架或操作更新将看起来不流畅。

以上是关于为啥我的应用程序最小化时 CPU 使用率会增加?的主要内容,如果未能解决你的问题,请参考以下文章

为啥意外的无限循环会增加 CPU 使用率?

为啥我的现有客户数量不断增加?

为啥这个 UPDATE 查询会杀死我的 CPU?

为啥我运行应用程序时 jar 文件的大小会增加?

为啥我的程序在 nVidia NView 下会消耗 100% CPU?

UWP:为啥我的后台任务(使用 TimeTrigger)会超出 CPU 配额?