当我的应用程序最小化时,为什么CPU使用会增加?

时间:2011-06-30 07:16:51

标签: c++ winapi opengl

我正在编写一个计算器。当窗口最大化时,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);
}

3 个答案:

答案 0 :(得分:6)

我的猜测是,如果active为false,您的主循环会毫无延迟地运行。线程无限地旋转通过该循环并使两个处理器核心中的一个保持忙碌(这就是为什么你看到50%的CPU负载)。

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

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

答案 1 :(得分:3)

OpenGL窗口覆盖的区域越小,绘制的场景越快(关键术语是 fillrate ),因此事件循环以更高的频率迭代。我看到你有一些函数RegulateFps - 对我而言,这听起来就像繁忙的循环,直到渲染器中消耗了一定的时间。即你真的在浪费CPU时间来获取......呃,你为什么要先保持帧率低?摆脱它。

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

尝试在驱动程序选项中启用V同步,并使用双重缓冲,然后wglSwapBuffers将阻止,直到垂直空白。如果active==falsePeekMessageGetMessage

答案 2 :(得分:0)

确定。我看到了你的一个逻辑流程。


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.

}