Страницы

Поиск по вопросам

воскресенье, 8 марта 2020 г.

Как усыпить текущий поток с возможностью возобновления из другого потока в Qt?

#cpp #qt #многопоточность #qt_faq


Имеется поток, который иногда засыпает(QThread::sleep) на довольно продолжительное
время (около 5 секунд). Если пользователь закрывает программу, то основной поток пытается
завершить уснувший, и ожидает его действительного завершения с помощью функции QThread::wait.
Но 5 секунд - достаточно продолжительное время, чтобы пользователь занервничал. В связи
с этим вопрос: как разбудить поток, который внутри себя вызвал функцию QThread::sleep?
    


Ответы

Ответ 1



Qt не предоставляет средств для пробуждения спящего потока. Но вместо этого можно использовать класс QWaitCondition с некоторой доработкой. Напишем для этого специальный класс. WakeableSleep.h: #ifndef WAKEABLESLEEP_H #define WAKEABLESLEEP_H #include #include #include #include /** * @brief Класс, который позволяет временно усыпить поток с возможностью пробуждения из другого потока. * * Класс можно создать в любом потоке. При вызове метода \ref sleep поток приостанавливается * на время, переданное с параметром. При вызове метода \ref wake из другого потока целевой * поток возобновляет выполнение независимо от истекшего времени. * \threadsafe */ class WakeableSleep : public QObject { Q_OBJECT public: explicit WakeableSleep(QObject *parent = 0); /** * @brief Усыпить текущий поток на milleseconds миллисекунд. * @param milliseconds Время сна. */ void sleep(quint32 milliseconds); /** * @brief wake Пробудить целевой поток из другого потока. */ void wake(); private: QMutex mutex; QWaitCondition waitCondition; }; #endif // WAKEABLESLEEP_H WakeableSleep.cpp: #include "wakeablesleep.h" WakeableSleep::WakeableSleep(QObject *parent) : QObject(parent){} void WakeableSleep::sleep(quint32 milliseconds) { mutex.lock(); waitCondition.wait(&mutex, milliseconds); mutex.unlock(); } void WakeableSleep::wake() { mutex.lock(); waitCondition.wakeAll(); mutex.unlock(); } Теперь вместо метода QThread::sleep можно использовать методы этого класса следующим образом: WakeableSleep sleeper; void Thread1() { sleeper.wake(); } void Thread2() { sleeper.sleep(5000); }

Комментариев нет:

Отправить комментарий