Qt:如何阻塞线程直到收到槽

问题描述 投票:0回答:1

我使用的是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);
c++ qt signals-slots qthread qmutex
1个回答
0
投票

我改变了我的方法,现在它正在发挥作用。我发布答案是因为它对某人有用,或者有人可以解释该解决方案是否适合最佳实践以及是否安全。

在我的 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;
}
© www.soinside.com 2019 - 2024. All rights reserved.