Страницы

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

воскресенье, 26 мая 2019 г.

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

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


Ответ

Qt не предоставляет средств для пробуждения спящего потока. Но вместо этого можно использовать класс QWaitCondition с некоторой доработкой. Напишем для этого специальный класс.
WakeableSleep.h:
#ifndef WAKEABLESLEEP_H #define WAKEABLESLEEP_H #include #include #include #include /** * @brief Класс, который позволяет временно усыпить поток с возможностью пробуждения из другого потока. * * Класс можно создать в любом потоке. При вызове метода
ef sleep поток приостанавливается * на время, переданное с параметром. При вызове метода
ef 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); }

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

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