如何在C语言中不使用多线程中断sleep()函数?
解决ncurses程序中无需多线程立即响应退出按键的问题
你可以通过两种无需多线程的方式实现需求,核心思路是用可中断的等待逻辑替代阻塞的sleep(1),让程序在等待期间仍能监听按键输入:
方案1:使用ncurses内置的超时机制
ncurses的getch()默认是阻塞的,你可以用timeout()函数设置它的超时时间(单位毫秒),这样就能替代sleep(1),同时在等待期间响应按键。
修改后的代码示例:
void run() { // 设置getch()最多等待1000毫秒(1秒),超时返回ERR timeout(1000); while (1) { for (int i = 0; i < num_things; ++i) { int ch = getch(); if (ch == 'q') { // 退出前必须清理ncurses终端环境 endwin(); return; } // 不管是超时还是其他按键,都更新内容 printw("Something"); refresh(); } } }
- 当
getch()超时(1秒到了),会返回ERR,程序继续执行内容更新;如果期间按下'q',会立即触发退出逻辑。 - 退出前务必调用
endwin(),否则终端会保持ncurses的特殊模式,导致后续操作异常。
方案2:使用select系统调用监听输入
如果需要更灵活的控制,可以用select()系统调用监听标准输入的可读事件,同时设置1秒超时,完全替代sleep(1)。
修改后的代码示例:
#include <sys/select.h> #include <unistd.h> void run() { fd_set read_fds; struct timeval tv; while (1) { for (int i = 0; i < num_things; ++i) { FD_ZERO(&read_fds); FD_SET(STDIN_FILENO, &read_fds); // 设置超时为1秒 tv.tv_sec = 1; tv.tv_usec = 0; int ret = select(STDIN_FILENO + 1, &read_fds, NULL, NULL, &tv); if (ret == -1) { perror("select"); endwin(); return; } else if (ret > 0) { // 有输入可读,读取按键判断是否退出 int ch = getch(); if (ch == 'q') { endwin(); return; } } printw("Something"); refresh(); } } }
select()会等待1秒,期间如果有按键按下,会立即返回并触发按键处理逻辑;超时后则继续执行内容更新。- 这种方式不依赖ncurses的内置超时,适合需要同时监听多个输入源的场景。
内容的提问来源于stack exchange,提问作者EwanMe
相关产品推荐
相关产品推荐

