Ich mache ein Timer-Programm, das die seit dem Start des Programms vergangene Zeit zählt. Im Hintergrund überprüfe ich auch auf Tastatureingabe (Enter/zurück zum Ausgang, klicke auf das Fenster); Dies geschieht in einem separaten Thread, den ich als gelöst ausgeführt habe.Benutzereingaben von einem anderen Thread übernehmen
Es scheint, dass der zweite Thread die Eingabe vom Hauptthread nicht empfangen kann. Wenn ich die Tastatur oder die Maus benutze, passiert nichts. Außerdem erscheint nichts auf dem Bildschirm, nur weiß.
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));
}
}
Ist meine Verwendung von Multithreading richtig? Wenn ja, kann nur der Haupt-Thread eine Eingabe erhalten und deshalb funktioniert es nicht?
Update: Wenn ich die while (true)
und while (window.pollEvent(event))
loszuwerden verwenden und die lock_guard
bis kurz vor if (stopProgram)
dann wird der Text (Zeitstempel) erscheint auf dem Bildschirm bewegen, aber ich kann immer noch nicht Eingang verarbeiten.
Aufruf von 'std :: this_thread :: sleep_for (std :: chrono :: Sekunden (1)); 'bedeutet nicht unbedingt, dass Ihr Programm in 1 Sekunde fortgesetzt wird. Also, wenn Sie eine genaue Zählung möchten, überprüfen Sie die Differenz zwischen der aktuellen Zeit und der vorherigen. –
"unique_lock" wird auch nur mit geteilten Mutexes verwendet. Die Verwendung von unique_lock bei nicht-gemeinsam genutzten Mutex ruft grundsätzlich 'lock_guard' auf. Sie sollten über freigegebene Mutexe auf http://en.cppreference.com/w/cpp/thread/shared_mutex lesen –
@TalShalti Wie überprüfe ich, ob der Unterschied in der Zeit genau eine Sekunde ist? –