Qt C++控制台程序如何实现带超时的用户输入,超时自动加载原有设置
Qt控制台程序带超时的用户输入实现方案
原有方案无法生效的核心原因是
std::cin为阻塞式IO,其等待输入的状态由操作系统内核维持,用户态的线程终止操作无法中断该内核级阻塞,强制终止线程还可能导致资源泄漏。
最优跨平台实现方案(推荐)
基于Qt原生QSocketNotifier配合事件循环实现,无需额外开启工作线程,完全规避阻塞IO问题,兼容Windows、Linux、macOS全平台:
- 首先通过平台兼容宏获取标准输入的文件描述符
- 实例化
QSocketNotifier绑定标准输入描述符,监听可读事件 - 实例化单次触发的
QTimer设置10秒超时,超时后直接执行默认加载逻辑 - 用户触发输入时
QSocketNotifier会收到信号,此时停止定时器再读取输入即可
示例代码
#include <QCoreApplication> #include <QSocketNotifier> #include <QTimer> #include <iostream> #ifdef Q_OS_WIN #include <io.h> #define STDIN_FILENO _fileno(stdin) #else #include <unistd.h> #define STDIN_FILENO fileno(stdin) #endif int main(int argc, char *argv[]) { QCoreApplication a(argc, argv); std::cout << "请选择操作:1-加载原有设置 2-设置新参数(10秒无输入默认加载原有设置)" << std::endl; // 初始化超时定时器 QTimer *timeoutTimer = new QTimer(&a); timeoutTimer->setSingleShot(true); timeoutTimer->setInterval(10000); // 初始化标准输入监听器 QSocketNotifier *stdinNotifier = new QSocketNotifier(STDIN_FILENO, QSocketNotifier::Read, &a); // 超时处理逻辑 QObject::connect(timeoutTimer, &QTimer::timeout, [&](){ std::cout << "\n超时,自动加载原有设置" << std::endl; stdinNotifier->setEnabled(false); // 此处补充加载原有设置的业务逻辑 a.quit(); }); // 用户输入处理逻辑 QObject::connect(stdinNotifier, &QSocketNotifier::activated, [&](){ timeoutTimer->stop(); stdinNotifier->setEnabled(false); int choice; std::cin >> choice; if (choice == 2) { std::cout << "进入新参数设置流程" << std::endl; // 此处补充新参数设置的业务逻辑 } else { std::cout << "加载原有设置" << std::endl; // 此处补充加载原有设置的业务逻辑 } a.quit(); }); timeoutTimer->start(); return a.exec(); }
备选多线程实现方案
如果业务架构必须使用多线程,可通过非阻塞轮询的方式避免std::cin长期阻塞:
- 工作线程中不要直接调用
std::cin读取,优先通过kbhit()(Windows)或select()(类Unix)接口检查标准输入是否有可读数据 - 每次检查间隔设为100ms,轮询间隙检测线程退出标志
- 超时触发时设置线程退出标志,工作线程检测到标志后直接退出,无需中断IO操作
- 仅当检测到有输入数据时,才调用
std::cin读取内容
内容的提问来源于stack exchange,提问作者Quirin
相关产品推荐
相关产品推荐

