我使用的是Qt 6.6.1。
我定义了一个类MyThread:
class MyThread: public QThread
作为内部类,我在.h文件的私有部分定义了一个类WakeUpEvent:
private:
class WakeUpEvent : public QEvent {
public:
static const QEvent::Type EventType = static_cast<QEvent::Type>(QEvent::User + 1);
WakeUpEvent() : QEvent(EventType) {}
};
然后,我重写事件方法:
protected:
bool event(QEvent* event) override {
if (event->type() == WakeUpEvent::EventType) {
// Wake-up event received
condition.wakeOne();
return true;
}
return QThread::event(event);
}
在私有部分我定义了3个变量:
QMutex mutex;
QWaitCondition condition;
bool shouldContinue;
最后,我定义了一个公共槽:
void MyThread::TaskCompleted()
{
shouldContinue = false;
// Send wake-up event to the thread
QCoreApplication::postEvent(this, new WakeUpEvent());
}
在我的代码中,我以这种方式阻止线程执行:
shouldContinue = true;
emit signalForAnotherThread();
// Sleep until wake-up event is received
while (shouldContinue) {
mutex.lock();
condition.wait(&mutex);
mutex.unlock();
}
signalForAnotherThread 是一个信号,它连接到另一个线程,我可以将其称为 thread2。 thread2 将执行一些任务,最后它将发出连接槽 TaskCompleted 的信号。
我确信,当我通过断点进行测试时,来自 thread2 的插槽 TaskCompleted 的信号已发出。但 TaskCompleted 永远不会达到(我通过断点检查)。
MyThread 块中执行的最后一行代码是
condition.wait(&mutex);
我的错误是什么?
TaskCompleted 以这种方式连接到 thread2 发出的信号:
connect(thread2, SIGNAL(tasksCompleted()), this, SLOT(TaskCompleted()), Qt::QueuedConnection);
我改变了我的方法,现在它正在发挥作用。我发布答案是因为它对某人有用,或者有人可以解释该解决方案是否适合最佳实践以及是否安全。
在我的 MyThread 类中,我删除了 QMutex 和 QWaitCondition。我只用一个 bool 值来决定 MyThread 是否必须继续执行:
bool shouldContinue;
然后我执行这段代码:
//Do something -> thread logic
shouldContinue = false;
emit signalForAnotherThread();
WaitForCompletion(shouldContinue);
//Do something -> thread logic
WaitForCompletion 是以下方法:
void MyThread::WaitForCompletion(const bool &bTermination)
{
//Waiting another thread completes its task and emits signal
while (!bTermination)
{
//Process Events for max 100 msec.
QCoreApplication::processEvents(QEventLoop::AllEvents, 100);
QThread::msleep(100);
}
}
在连接指令中,我按照建议放弃了使用 SIGNAL / SLOT 宏。
connect(&thread2, &Thread2Class::taskCompleted, &myThread, &MyThread::TaskCompleted, Qt::QueuedConnection);
最后在 TaskCompleted 槽中我将 shouldContinue 设置为 true:
void MyThread::TaskCompleted()
{
shouldContinue = true;
}