使用 getch() 的循环条件不会按预期结束循环
Loop condition using getch() does not end the loop as expected
我有以下代码,但即使 done
为真,它也不会结束 while
循环。它一直在等待 _getch()
:
while (done || ((c = _getch()) != EOF))
{
cout << "Operation aborted" << endl;
break;
}
cout << "Operation finished" << endl;
编辑: 事实上,我希望能够中断在另一个线程中执行的长时间操作。我相信我必须在 while
循环之后加入线程。但是使用下面的代码,当我按下一个键时,循环不会被执行。
thread t(Start, folder_path);
while (done || ((c = _getch()) != EOF))
{
cout << "Operation aborted" << endl;
exit_signal.set_value();
break;
}
t1.join();
cout << "Operation finished" << endl;
当 done
为真时如何结束循环?
循环条件的写法是:
- 如果
done
为真,逻辑表达式被短路并进入循环体而不评估条件的右侧。
- 如果
done
为假,则调用 _getch()
。如果返回的是char,则表达式为真,进入循环体。如果没有可用的字符,_getch()
将等待用户键入一个字符。只有遇到文件末尾(即在终端模式下输入 Ctrl+Z,或从文件重定向 cin 并到达其末尾),循环才会被中断。
如果你想要一个非阻塞的键盘输入,你必须使用 _kbhit()
first, to check if a char is available, and then only read the char with _getch()
. For kbhit()
on linux, you may have a look 。
编辑:您的多线程编辑
首先,如果 done
是一个在两个线程中都使用的变量(显然是这样,因为它在循环中没有改变),确保它声明为 atomic
。如果不是这种情况,那么您的竞争条件就是 UB。
现在,您的叙述与代码不符。如果 done
是另一个线程完成的时候,而你想在这一刻结束循环,你需要在 !done
上循环。
此外,如果你想在另一个线程运行时循环,但检查键盘并让用户中断代码,你最好在循环中进行检查。顺便说一下,可以选择在循环体中运行 sleep_for
几毫秒,以避免浪费太多 CPU 来查询键盘。
所以代码最终会以
这样的结构结束
std::atomic<bool> done(false);
...
thread t(Start, folder_path);
while (!done)
{
if (_kbhit() && ((c = _getch()) != EOF) { // if keystroke available
cout << "Operation aborted" << endl;
exit_signal.set_value(); // assuming this would make t1 return from folder_path()
break;
}
std::this_thread::sleep_for (std::chrono::milliseconds(500));
// update status bar or do other stuff
}
t1.join();
cout << "Operation finished" << endl;
终于不知道exit_signal.set_value();
在干什么了。我希望它确实做了一些事情来告诉另一个线程停止处理。如果没有,您的循环将结束,但在 join()
处您无论如何都必须等待另一个线程完成。
我有以下代码,但即使 done
为真,它也不会结束 while
循环。它一直在等待 _getch()
:
while (done || ((c = _getch()) != EOF))
{
cout << "Operation aborted" << endl;
break;
}
cout << "Operation finished" << endl;
编辑: 事实上,我希望能够中断在另一个线程中执行的长时间操作。我相信我必须在 while
循环之后加入线程。但是使用下面的代码,当我按下一个键时,循环不会被执行。
thread t(Start, folder_path);
while (done || ((c = _getch()) != EOF))
{
cout << "Operation aborted" << endl;
exit_signal.set_value();
break;
}
t1.join();
cout << "Operation finished" << endl;
当 done
为真时如何结束循环?
循环条件的写法是:
- 如果
done
为真,逻辑表达式被短路并进入循环体而不评估条件的右侧。 - 如果
done
为假,则调用_getch()
。如果返回的是char,则表达式为真,进入循环体。如果没有可用的字符,_getch()
将等待用户键入一个字符。只有遇到文件末尾(即在终端模式下输入 Ctrl+Z,或从文件重定向 cin 并到达其末尾),循环才会被中断。
如果你想要一个非阻塞的键盘输入,你必须使用 _kbhit()
first, to check if a char is available, and then only read the char with _getch()
. For kbhit()
on linux, you may have a look
编辑:您的多线程编辑
首先,如果 done
是一个在两个线程中都使用的变量(显然是这样,因为它在循环中没有改变),确保它声明为 atomic
。如果不是这种情况,那么您的竞争条件就是 UB。
现在,您的叙述与代码不符。如果 done
是另一个线程完成的时候,而你想在这一刻结束循环,你需要在 !done
上循环。
此外,如果你想在另一个线程运行时循环,但检查键盘并让用户中断代码,你最好在循环中进行检查。顺便说一下,可以选择在循环体中运行 sleep_for
几毫秒,以避免浪费太多 CPU 来查询键盘。
所以代码最终会以
这样的结构结束std::atomic<bool> done(false);
...
thread t(Start, folder_path);
while (!done)
{
if (_kbhit() && ((c = _getch()) != EOF) { // if keystroke available
cout << "Operation aborted" << endl;
exit_signal.set_value(); // assuming this would make t1 return from folder_path()
break;
}
std::this_thread::sleep_for (std::chrono::milliseconds(500));
// update status bar or do other stuff
}
t1.join();
cout << "Operation finished" << endl;
终于不知道exit_signal.set_value();
在干什么了。我希望它确实做了一些事情来告诉另一个线程停止处理。如果没有,您的循环将结束,但在 join()
处您无论如何都必须等待另一个线程完成。