无法为处于不同线程 qt C++ 中的父对象创建子对象

Cannot create children for a parent that is in a different thread qt c++

我正在尝试 运行 与主线程分开的线程,其中 mqttclient 已初始化并移动到新线程。

之前信号槽有问题。我通过从主线程创建一个单独的 class (mqtthandler) 运行ning 并通过传送到的信号槽连接到 mqttclient class 来恢复qml.

我通过 运行在同一线程中测试代码。他们都工作。

现在,当我尝试在另一个线程中移动 mqttclient 时,它 导致 问题 。我知道它给我带来问题的原因,但我不知道解决方案。

问题的创造者是 mqttclient constructor 因为它 connecttohost 仅在构造函数中。 我需要 connecttohost mqttclient 但不知何故在新线程中。

我还 尝试在订阅函数(mqttclient 本身)中创建 connecttohost ,稍后通过 mqtthandler 调用通过 qml。仍然不起作用。

main.cpp

  QGuiApplication app(argc, argv);

    QThread mqttclientThread;

    // When the application is quitting, so should the worker thread
    QObject::connect(&app, &QCoreApplication::aboutToQuit, &mqttclientThread, &QThread::quit);

    MqttClient * mqttclientObj = new MqttClient;

    mqttclientObj->moveToThread(&mqttclientThread);

    mqttclientThread.start();

    qDebug() << "Main client status " << mqttclientObj->state();

    MqttHandler * mqttHandlerObj = new MqttHandler;
    QObject::connect(mqttHandlerObj, &MqttHandler::mqtthandler_getaddr_signal, mqttclientObj, &MqttClient::getAddr);
    QObject::connect(mqttclientObj, &MqttClient::sensorValueChanged, mqttHandlerObj,&MqttHandler::mqtthandler_sensorValueChanged_slot);


    qDebug() << "Main " << QThread::currentThread();  

mqttclient.cpp

MqttClient::MqttClient(QObject *parent)
    : QMqttClient(parent)
{

    this->setHostname("127.0.0.1");
    this->setPort(1883);
    this->connectToHost();



    m_listTopic.clear();
    vSimulateSensorValues();
   connect(this, SIGNAL(publishsignals(QString, QString)),this, SLOT(publishmsg(QString,QString)));
}

MqttSubscription* MqttClient::subscribe(const QString &topic)
{

    auto sub = QMqttClient::subscribe(topic, 0);

    MqttSubscription*  result = new MqttSubscription(sub, this);

    qDebug() << "subscribe " << QThread::currentThread();

    m_listTopic.append(topic);

    return result;
}

MqttSubscription::MqttSubscription(QMqttSubscription *s, MqttClient *c)
    : sub(s),
      client(c)
{    
    connect(sub, &QMqttSubscription::messageReceived, client, &MqttClient::handleMessage);
    qDebug() << "mqttsubconn " << QThread::currentThread();
}

MqttSubscription::~MqttSubscription()
{
}

错误

Main client status  1
Main  QThread(0x7fcfa7400530)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QMqttConnection(0x7fcfa75a3008), parent's thread is QThread(0x7fcfa7400530), current thread is QThread(0x7ffee1cb4a30)
QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

/******************************************** ****************************************************** ****************************************************** ****************************************************** ******************************/

更新

更新了 mqttclient class

    MqttClient::MqttClient(QObject *parent)
        : QMqttClient(parent)
    {
    }

    void MqttClient::Init()
    {
        this->setHostname("127.0.0.1");
        this->setPort(1883);
        this->connectToHost();

        QThread::sleep(10);

        m_listTopic.clear();
        vSimulateSensorValues();
        connect(this, &MqttClient::publishsignals, this, &MqttClient::publishmsg);
    }

    MqttSubscription* MqttClient::subscribe(const QString &topic)
    {

     //   this->setParent(this);

        auto sub = QMqttClient::subscribe(topic, 0);
        qDebug() << "state " << this->state();

        MqttSubscription*  result = new MqttSubscription(sub, this);

        qDebug() << "subscribe " << QThread::currentThread();

        m_listTopic.append(topic);

        return result;
    }

void MqttClient::handleMessage(const QMqttMessage &qmsg)
{
    emit MqttClient::sensorValueChanged(qmsg.payload(),qmsg.topic().name());
    qDebug() << "Handle " << QThread::currentThread();
}

void MqttClient::getAddr(QString value)
{

    qDebug() << "c++ " + value;
    subscribe(value);
    qDebug() << "getaddr " << QThread::currentThread();
}

    MqttSubscription::MqttSubscription(QMqttSubscription *s, MqttClient *c)
        : sub(s),
          client(c)
    {
        qDebug() << "Here " << client->state();
        qDebug() << client;

        connect(sub, &QMqttSubscription::messageReceived, client, &MqttClient::handleMessage);
        qDebug() << "mqttsubconn " << QThread::currentThread();
    }

    MqttSubscription::~MqttSubscription()
    {
    }

和main.cpp

QGuiApplication app(argc, argv);

QThread mqttclientThread;

// When the application is quitting, so should the worker thread
QObject::connect(&app, &QCoreApplication::aboutToQuit, &mqttclientThread, &QThread::quit);

MqttClient * mqttclientObj = new MqttClient;

mqttclientObj->moveToThread(&mqttclientThread);

QObject::connect(&mqttclientThread, &QThread::started, mqttclientObj, &MqttClient::Init);
mqttclientThread.start();

MqttHandler * mqttHandlerObj = new MqttHandler;
QObject::connect(mqttHandlerObj, &MqttHandler::mqtthandler_getaddr_signal, mqttclientObj, &MqttClient::getAddr);
QObject::connect(mqttclientObj, &MqttClient::sensorValueChanged, mqttHandlerObj,&MqttHandler::mqtthandler_sensorValueChanged_slot);


qDebug() << "Main " << QThread::currentThread();

更新引起了另一个问题

    Main  QThread(0x7f925750e790)
    state  1
    Here  1
    MqttClient(0x7f9257600f90)
    QObject::connect(QMqttSubscription, MqttClient): invalid null parameter
QSocketNotifier: Socket notifiers cannot be enabled or disabled from another thread

如果问题如您所建议的那样,是在 MqttClient 构造函数中对 connectToHost 的调用,那么为什么不简单地将有问题的代码移到一个插槽中呢?

MqttClient::MqttClient(QObject *parent)
    : QMqttClient(parent)
{
}

void MqttClient::init ()
{
    this->setHostname("127.0.0.1");
    this->setPort(1883);
    this->connectToHost();
    m_listTopic.clear();
    vSimulateSensorValues();
    connect(this, &MqttClient::publishsignals, this, &MqttClient::publishmsg);
}

然后在 main 中将该插槽连接到 QThread::started 信号...

    .
    .
    .
MqttClient *mqttclientObj = new MqttClient;
mqttclientObj->moveToThread(&mqttclientThread);

/*
 * Connect MqttClient::init slot to QThread::started signal.
 */
connect(&mqttclientThread, &QThread::started, mqttclientObj, &MqttClient::init);
mqttclientThread.start();
    .
    .
    .