无法为处于不同线程 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();
.
.
.
我正在尝试 运行 与主线程分开的线程,其中 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();
.
.
.