基于C++线程实现可选键盘中断退出while循环的问题
解决Windows下非阻塞键盘中断退出循环的问题
你的问题核心是把t.join()放错位置啦——join()会让当前线程(也就是主线程)一直等待子线程完成,你把它放在while循环里,第一次循环执行后主线程就停下来等子线程的输入了,自然循环只跑一次。下面给你两种可行的实现方案:
方案1:修正你的线程思路
首先要调整线程的等待时机,还要保证共享变量的线程安全(多线程读写同一个变量时,普通int可能会出现竞态问题,所以用std::atomic来确保原子操作):
#include <iostream> #include <thread> #include <atomic> #include <chrono> // 用原子类型保证多线程读写的安全性 std::atomic<int> exitWhile = 0; void interrupt() { // 子线程后台等待用户输入1,输入后修改退出标记 std::cin >> exitWhile; } int main() { std::thread t(interrupt); // 把join()移到循环外面,让子线程和主线程并行运行 while (exitWhile != 1) { std::cout << "Inside while loop" << std::endl; // 加个小延迟,避免输出太快刷屏 std::this_thread::sleep_for(std::chrono::milliseconds(500)); } // 循环退出后再等待子线程结束 t.join(); std::cout << "Exit while.\n"; return 0; }
这样主线程的while循环会持续运行,子线程在后台等待用户输入,一旦输入1,exitWhile的原子操作会立刻让主线程检测到,从而退出循环,最后再等待子线程完成。
方案2:用Windows API实现无等待按键检测(无需额外线程)
如果你不想用线程,Windows提供了GetAsyncKeyState函数,可以非阻塞地检测键盘按键状态,比如按下ESC键就退出循环,这样更简洁:
#include <iostream> #include <chrono> #include <thread> // 需要包含Windows头文件 #include <Windows.h> int main() { while (true) { std::cout << "Inside while loop" << std::endl; // 检测ESC键是否被按下(GetAsyncKeyState返回值的最高位为1表示按键按下) if (GetAsyncKeyState(VK_ESCAPE) & 0x8000) { break; } // 延迟避免刷屏 std::this_thread::sleep_for(std::chrono::milliseconds(500)); } std::cout << "Exit while.\n"; return 0; }
这个方案不需要额外线程,直接在循环里非阻塞检测按键,按下ESC就立刻退出,完全符合你“循环持续运行,直到用户主动终止”的需求。
内容的提问来源于stack exchange,提问作者nicolas005
相关产品推荐
相关产品推荐

