【问题标题】:Why is this thread slot not getting called?为什么这个线程槽没有被调用?
【发布时间】:2020-11-21 02:08:59
【问题描述】:

Two.h

#ifndef TWO_H
#define TWO_H

#include <QObject>
#include <QThread>
#include <QDebug>
#include <QTimer>

class Two : public QObject
{
   Q_OBJECT

private:
    QTimer abc;
public:
    QString m_xyz;
    Two();

signals:
    void emitThisSignal( int x, QString &y );

public slots:
    void mySlot();
};


class Controller : public QObject
{
    Q_OBJECT

private:
    Two objTwo;

    QThread objQThread;

    Controller();

public slots:
    void mySlot( int x, QString &y)
    {
        qDebug() << "\nWWWWWWWWWWWWW: " << y;
    }
};

#endif // TWO_H

两个.cpp

#include "two.h"

Two::Two()
{
    m_xyz = "aksja";

    QTimer *timer = new QTimer(this);
    connect(timer, &QTimer::timeout, this, &Two::mySlot);
    timer->start(1000);
}

void Two::mySlot()
{
    emit emitThisSignal(4, m_xyz);
    qDebug()<< "FFFFFFFFFFF " << m_xyz;
}

Controller::Controller()
{
    objTwo.moveToThread( &objQThread );

    connect( &objTwo, &Two::emitThisSignal, this, &Controller::mySlot );
    connect( &objQThread, &QThread::finished, &objQThread, &QThread::deleteLater );

    objQThread.start();
}

Controller::~Controller()
{
    delete objTwo;
    objQThread.wait();
}

我可以看到由于 print 语句而发出了信号,但没有调用 Controller 类的插槽。

void Two::mySlot()
    {
        emit emitThisSignal(4, m_xyz);
        qDebug()<< "FFFFFFFFFFF " << m_xyz;
    }

为什么会这样?

int main( int argc, char* argv[])
{
    QCoreApplication app(argc, argv);
    Controller o;

    return app.exec();
}

【问题讨论】:

  • 你如何使用Controller?它是如何实例化的,你是否在它的线程(可能是主线程)上运行事件循环。
  • @MarekR 我应该在哪里运行事件循环?请写出答案。

标签: c++ multithreading qt qthread


【解决方案1】:

请参阅QObject::connect 的文档,注意最后一个带有默认值的参数:Qt::AutoConnection

Its documentation says:

(默认)如果接收者lives in是发出信号的线程,则使用Qt::DirectConnection。否则,使用 Qt::QueuedConnection。连接类型在信号发出时确定。

现在你陷入了Qt::QueuedConnection 场景:

当控制返回到接收者线程的事件循环时调用该槽。该槽在接收者的线程中执行。

所以基本上你需要一些可以提供事件循环的东西。

在这段代码中你需要:

int main( int argc, char* argv[])
{
    QCoreApplication app{argc, argv};
    Controller o;

    // note you need something what will stop this event loop to terminate application
    return app.exec();
}

还有一件事。 现在我注意到您的信号和插槽参数非常不寻常。问题可能是第二个参数是QString&amp;

这可能是问题的根源,我不知道 Qt 是否能够编组非 const 引用。如果您添加 const,那么它将能够编组 QString 并且应该可以工作(如果我没有错过其他陷阱的话)。

【讨论】:

  • 应该。确保正确重建它。我现在没有时间在我的机器上验证这一点。也许在 10 小时内
  • @Aquarius_Girl 每个帖子一个问题。至于您的编辑,我之前已经在您的问题中回答了这个问题,但您似乎没有费心去阅读它。您正在删除堆栈上的一个对象(objTwo)。那是未定义的行为。而deleteLater 在这里完全没有意义。
  • @Waqar 我确实阅读了您的帖子并且确实理解了它。我只是懒得删除 deleteLater 语句,因为它目前没有造成任何麻烦。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多