简体   繁体   中英

Making program use less CPU when waiting in an infinite loop

Setup : I have this program in c++:

#include <windows.h>
using namespace std;
int main(){
    HWND window;
    AllocConsole();
    window = FindWindowA("ConsoleWindowClass", NULL);
    ShowWindow(window,0);
while (1){  
if (GetKeyState('A'))
        {
    system("start love.mp3");
    return 0;
        }
    }
return 0;
}

So the program runs as a process and waits until the key A is pressed. And then it plays the love.mp3 file :)

However, when the program is waiting it uses up 25% of the CPU usage.

Qustion : Is there a way to reduce this so that the program doesn't consume so much of the CPU?

Your program is guilty of busy-waiting .

Try hooking your keyboard calls by using SetWindowsHookEx .

Calling Sleep in the loop is sort of effective, but IMO, it's clearly the wrong way to go.

Instead, I'd do a blocking read, then check if the result was A , and do your thing when it is:

while ((ch = getch()) != EOF)
    if (ch == 'A') {
        system("start love.mp3");
        break;
    }

This won't miss keystrokes, and it'll use even less CPU time than a loop that calls Sleep .

You can stick a call to the Windows Sleep() function into the loop pretty easily. The argument is in milliseconds, so this will check the keyboard roughly five times a second:

#include <windows.h>
// ...
while (1){  
    if (GetKeyState('A'))
    {
        system("start love.mp3");
        return 0;
    }
    Sleep(200);
}

The way to do this would be to use a Windows hook, probably of type WH_KEYBOARD or WH_KEYBOARD_LL hook (although WH_GETMESSAGE would work as well) and do your processing there. 方法是使用Windows挂钩,可能是WH_KEYBOARD或WH_KEYBOARD_LL挂钩类型(尽管WH_GETMESSAGE也可以工作)并在那里进行处理。

Look at the documentation for SetWindowsHookEx at http://msdn.microsoft.com/en-us/library/windows/desktop/ms644990(v=vs.85).aspx

I haven't tested this - just whipped it up on the fly - but here's a simple example that should do what you want when the 'A' key is pressed.

LRESULT __stdcall CALLBACK LoveProc(int nCode, WPARAM wParam, LPARAM lParam)
{
    static int love = 0;

    if((nCode == HC_ACTION) && 
       (wParam == 'A') &&      /* the key pressed was 'A' */
       (lParam & 0x40000000))  /* trigger when the key is pressed */
    {        
        if(love == 0)
            play_romantic_love_song();

        /* but don't overdo it because "Too Much Love Will Kill You" */
        love = 1;
    }

    return CallNextHookEx(hOldKeyHook, nCode, wParam, lParam );
}

You may also want to google for "*SetWindowsHookEx WH_KEYBOARD*" as I'm pretty sure there's at least a couple of articles that explain this on CodeProject. I'd include the links, but I'm typing this from my iPhone and it's being... difficult.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM