目的
了解下我们常在打印的日志中见过如下类似字符串:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QThread(xxxxxx), parent's thread is QThread(xxxxxx), current thread is QThread(xxxxxx)
初次见到, 我们为此经常感到头疼。
现象分析
按字面意思可以理解为: 不能为属于不同线程的父对象创建子对象。 也就是当前线程与父对象属于的线程不是同一个线程, 我们不能为此创建该子类。
- 有个核心要知道的是, 在QThread中定义的所有东西都属于创建该QThread的线程。
在类中如下声明子对象成员时
class A; //在对象一生成,就默认为隶属于创建该父类 包括所属线程关系
class A* = new A(this); // new 的时候 就默认为隶属于创建该父类 包括所属线程关系
#ifndef MyTest_H
#define MyTest_H
#include <QThread>
#include <QDebug>
class ObjectOne : public QObject
{
public:
Class1(QObject* parent) : QObject(parent){}
};
class ObjectOneThread : public QThread
{
public:
ObjectOneThread ()
{
qDebug() << "ObjectOneThread, thread = " << QThread::currentThread();
}
void run() override
{
qDebug() << "ObjectOneThread::run, thread = " << QThread::currentThread();
qDebug() << "ObjectOneThread::run, " << this->thread();
m_class = new ObjectOne (this);
}
private:
ObjectOne * m_class = nullptr;
};
#endif // MyTest_H
main.cpp
#include "mytest.h"
#include <QGuiApplication>
#include <QDebug>
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
ObjectOneThread thread;
thread.start();
return app.exec();
}
运行如下:
ObjectOneThread, thread = QThread(0x2675852480)
ObjectOneThread::run, thread = QThread(0x8d9d4ff7a8)
ObjectOneThread::run, QThread(0x2675852480)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QThread(0x8d9d4ff7a8), parent's thread is QThread(0x2675852480), current thread is QThread(0x8d9d4ff7a8)
由运行结果看出 thread2(ThreadTest2)属于主线程(QThread(0x2675852480)),我们尝试在 QThread(0x8d9d4ff7a8)线程中为属于(QThread(0x2675852480))的 thread2 对象创建子对象。
方案
针对此方案
- 创建对象时尽量不要指定父对象
- 使用moveToThread设置对象绑定的线程
- 将子对象的创建放到启动执行线程的线程中完成