Почему увеличивается загрузка процессора, когда мое приложение свернуто? - PullRequest
4 голосов
/ 30 июня 2011

Я программирую калькулятор.Когда окно развернуто, загрузка процессора составляет около 12%, но когда оно свернуто, загрузка процессора возрастает до 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 ]

6 голосов
/ 30 июня 2011

Я предполагаю, что ваш основной цикл работает без задержек, если active имеет значение false.Поток бесконечно вращается в этом цикле и поддерживает занятость одного из двух процессорных ядер (вот почему вы видите 50% загрузки процессора).

Если active имеет значение true, операция подкачки ожидает следующего vsync и задерживаетваш цикл до следующего обновления экрана, что приводит к снижению нагрузки на процессор.(Время, которое поток тратит на ожидание внутри функции Windows в ожидании события, не учитывается при загрузке процессора.)

Чтобы решить эту проблему, вы можете переключиться на GetMessage -цикл сообщений на время, когда вы не хотите ничего визуализировать.

3 голосов
/ 30 июня 2011

Чем меньше площадь вашего окна OpenGL, тем быстрее рисуется сцена (ключевым термином является fillrate ), и, таким образом, цикл обработки событий повторяется с более высокой частотой.Я вижу, у вас есть какая-то функция RegulateFps - для меня это звучит как что-то, что занято зацикливается, пока в рендере не будет использовано определенное время.Т.е. вы буквально тратите время процессора, чтобы получить… э-э-э, зачем вам в первую очередь поддерживать низкую частоту кадров?Избавьтесь от этого.

И, конечно, если вы его минимизируете, вы устанавливаете active = false, так что вообще не выполняете вещи GL, но все равно теряете время в занятом цикле.V синхронизации в настройках драйвера и использовать двойную буферизацию, тогда wglSwapBuffers будет блокироваться до вертикального пробела.И если active==false не PeekMessage, а GetMessage

0 голосов
/ 30 июня 2011

Хорошо.Я вижу один из ваших логических потоков.


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.

}

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...