Ncurses 莫名其妙地无缘无故地使用了我所有的 CPU

问题描述

我正在尝试使用 ncurses 编写类似 nethack 的程序。该程序运行良好,完美地为我绘制了一个盒子和所有内容,同时不会占用我的 cpu添加 while(true) 循环后,它不会绘制我的框,并且当我移动“角色”时它会占用我 100% 的 cpu

#include <iostream>
#include <curses.h>
int main(){
    std::pair<int,int> csr_pos{1,1};
    initscr();
    cbreak();
    noecho();
    keypad(stdscr,TRUE);
    nodelay(stdscr,TRUE);
    curs_set(0);
    WINDOW *win = newwin(50,80,0);
    if(has_colors()){
        start_color();
        init_pair(1,COLOR_CYAN,COLOR_BLACK);
        init_pair(2,COLOR_RED,COLOR_BLACK);
        init_pair(3,COLOR_WHITE,COLOR_RED);
        init_pair(4,COLOR_YELLOW,COLOR_BLACK);
    }
    /*
    wattron(win,COLOR_PAIR(1));
    mvwaddch(win,25,41,'@');
    wattroff(win,COLOR_PAIR(1));
    */
    for(int i = 0; i<80; i++){
        mvwaddch(win,i,'#');
        mvwaddch(win,49,'#');
        wrefresh(win);
    }
    for(int i = 1; i<49; i++){
        mvwaddch(win,79,'#');
        wrefresh(win);
    }
    while(true){
        mvwaddch(win,csr_pos.first,csr_pos.second,'@');
        int ch = getch();
        if(ch==KEY_LEFT){
            mvwaddch(win,' ');
            csr_pos.second--;
            mvwaddch(win,'@');
        }
        if(ch==KEY_RIGHT){
            mvwaddch(win,' ');
            csr_pos.second++;
            mvwaddch(win,'@');
        }
        wrefresh(win);
    }
}

解决方法

nodelay(stdscr,TRUE);

让我们看看curses手册页是怎么说的:

 nodelay
   The nodelay option causes getch to be a non-blocking call.  If no input
   is  ready,getch  returns ERR.  If disabled (bf is FALSE),getch waits
   until a key is pressed.

如果还不清楚:在 nodelay 模式下,getch 不会等待按键。它立即返回。

让我们看看显示的代码接下来做了什么:

while(true){
    mvwaddch(win,csr_pos.first,csr_pos.second,'@');
    int ch = getch();

// ...

所以,这现在变成了一个 100% CPU 绑定的无限循环。 getch 总是立即返回。如果以下代码检查的两个键都没有按下,则此 while 循环会立即再次运行,并且您会一遍又一遍地回到起点。

这就是显示的代码“吃掉 100%”CPU 的原因。

nodelay 模式旨在与 poll()select() 的附加逻辑一起使用,直到有按键,并且 getch 仅在有实际按键时才被调用待读。