【发布时间】:2016-12-19 22:32:12
【问题描述】:
我正在制作一个计时器程序来计算程序启动后经过的时间。在后台我也在检查键盘输入(进入/返回退出,点击窗口);这是在我以 detached 身份运行的单独线程中完成的。
似乎第二个线程无法接收来自主线程的输入。当我使用键盘或鼠标时,没有任何反应。此外,屏幕上什么也没有出现,只有白色。
std::mutex g_mutex;
std::condition_variable cv;
// check for input from the user using the window object
// sets stopProgram to true if the user wishes to exit
void poll(sf::RenderWindow& window, bool& stopProgram) {
std::unique_lock<std::mutex> lk(g_mutex);
// wait for main thread to open window
cv.wait(lk, [&] { return !stopProgram && window.isOpen(); });
sf::Event event;
while (true) {
if (window.pollEvent(event)) {
// if user wants to exit program
if (event.type == sf::Event::Closed || (event.type == sf::Event::KeyPressed &&
(event.key.code == sf::Keyboard::Return || event.key.code == sf::Keyboard::Escape))) {
window.close();
// main thread will explicitly exit the main loop
stopProgram = true;
break;
}
}
}
}
int main()
{
int hour = 0, minute = 0, second = 0;
auto text = textObject();
bool stopProgram = false;
// run a background thread that checks for input while the main program runs
std::thread(poll, std::ref(window), std::ref(stopProgram)).detach();
std::once_flag flag;
std::lock_guard<std::mutex> lk(g_mutex);
while (window.isOpen()) {
// notify once window opens
std::call_once(flag, [&] { cv.notify_one(); });
// set timestamp
text->setString(makeTimeStamp(hour, minute, second));
// if the background thread set stopProgram, end the program
if (stopProgram) break;
window.clear(sf::Color::White);
window.draw(*text);
window.display();
// update time
second = (second + 1) % MAX_SEC;
if (second == 0) minute = (minute + 1) % MAX_MIN;
if (second == 0 && minute == 0) hour = (hour + 1) % MAX_HOUR;
// sleep one second
std::this_thread::sleep_for(std::chrono::seconds(1));
}
}
我对多线程的使用正确吗?如果是这样,只能主线程接收输入,这就是它不起作用的原因吗?
更新:如果我去掉 while (true) 并使用 while (window.pollEvent(event)) 并将 lock_guard 移动到 if (stopProgram) 之前,那么文本(时间戳)会出现在屏幕上,但我仍然无法处理输入。
【问题讨论】:
-
调用
std::this_thread::sleep_for(std::chrono::seconds(1));并不一定意味着您的程序将在1 秒内恢复。因此,如果您想要准确计数,请检查当前时间与上一个时间之间的差异。 -
另外,
unique_lock仅用于共享互斥锁。在非共享互斥锁上使用 unique_lock 基本上是调用lock_guard。您应该在en.cppreference.com/w/cpp/thread/shared_mutex 上阅读有关共享互斥锁的信息 -
@TalShalti 如何检查时间差是否正好是一秒?
-
睡一秒只能保证你至少睡一秒。要计算时间差,请在要计算时间的事物之前和之后使用函数
std::chrono::system_clock::now(),然后从另一个值中减去一个值 -
你不能只使用全局值和/或函数吗?无论线程如何,您都可以访问相同的函数和全局变量
标签: c++ multithreading c++11 sfml