Question:
There is a thread that sometimes sleeps ( QThread::sleep
) for quite a long time (about 5 seconds). If the user exits the program, the main thread tries to terminate the sleeping one and waits for it to actually terminate using the QThread::wait
function. But 5 seconds is long enough to make the user nervous. In this regard, the question is: how to wake up a thread that has called the QThread::sleep
function inside itself?
Answer:
Qt does not provide a means to wake up a sleeping thread. But you can use the QWaitCondition
class QWaitCondition
with some tweaking. Let's write a special class for this.
WakeableSleep.h:
#ifndef WAKEABLESLEEP_H
#define WAKEABLESLEEP_H
#include <QObject>
#include <QThread>
#include <QMutex>
#include <QWaitCondition>
/**
* @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();
}
Now, instead of the QThread::sleep
method, you can use the methods of this class as follows:
WakeableSleep sleeper;
void Thread1()
{
sleeper.wake();
}
void Thread2()
{
sleeper.sleep(5000);
}