QThread 爬坑之旅(三种办法解决QObject: Cannot create children for a parent that is in a different thread)
解决 for in is Cannot 三种 create thread
2023-09-11 14:19:08 时间
Cannot create children for a parent that is in a different thread.
在Qt的官方文档,大家知道有两种方式使用 QThread。
- You can use worker objects by moving them to the thread using QObject::moveToThread().
- Another way to make code run in a separate thread, is to subclass QThread and reimplement run().
在使用MoveToThread这种方式时,经常会遇到下面类似的问题:
- QObject: Cannot create children for a parent that is in a different thread.
出现这样的问题根本原因就是,调用MoveToThread 之后,在 Worker的槽函数中Worker的私有成员中又进行了new操作,并且将this指针传给了构造函数。看下实例:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QThread>
#include <QMainWindow>
#include "worker.h"
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
signals:
void doWorkSignal();
private:
Ui::MainWindow *ui;
QThread m_thread;
Worker m_worker;
};
#endif // MAINWINDOW_H
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_worker.moveToThread(&m_thread);
connect(this, SIGNAL(doWorkSignal()),
&m_worker, SLOT(doWork()));
m_thread.start();
emit doWorkSignal();
qDebug() << "MainWin thread: " << QThread::currentThread();
}
MainWindow::~MainWindow()
{
delete ui;
m_thread.exit();
m_thread.wait();
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
#include <QThread>
#include <QNetworkAccessManager>
class WorkerA: public QObject
{
Q_OBJECT
public:
inline explicit WorkerA(QObject *parent = 0)
{
m_net1 = new QNetworkAccessManager(this);
qDebug() << "Create WorkerA thread: " << QThread::currentThread();
}
inline void doWorkA()
{
m_net2 = new QNetworkAccessManager(this);
qDebug() << "DoWorkA thread: " << QThread::currentThread();
qDebug() << "Net1 Parent: " << m_net1->parent();
qDebug() << "Net2 Parent: " << m_net2->parent();;
}
inline ~WorkerA()
{
delete m_net1;
delete m_net2;
}
private:
QNetworkAccessManager *m_net1;
QNetworkAccessManager *m_net2;
};
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker(QObject *parent = 0);
~Worker();
signals:
public slots:
void doWork();
private:
WorkerA *m_workerA;
};
#endif // WORKER_H
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
worker.cpp
#include <QDebug>
#include "worker.h"
Worker::Worker(QObject *parent) :
QObject(parent)
{
m_workerA = new WorkerA(this);
qDebug() << "Create Worker thread: " << QThread::currentThread();
}
void Worker::doWork()
{
qDebug() << "doWork thread: " << QThread::currentThread();
m_workerA->doWorkA();
}
Worker::~Worker()
{
//delete m_workerTimer;
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
程序运行输出:
Create WorkerA thread: QThread(0x4482e8)
Create Worker thread: QThread(0x4482e8)
MainWin thread: QThread(0x4482e8)
doWork thread: QThread(0x28fe1c)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is WorkerA(0x4558a8), parent's thread is QThread(0x4482e8), current thread is QThread(0x28fe1c)
DoWorkA thread: QThread(0x28fe1c)
Net1 Parent: WorkerA(0x4558a8)
Net2 Parent: QObject(0x0)
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
在本案例中,Worker在槽函数中调用私有成员WorkerA的doWorkA(),doWorkA()中
m_net2 = new QNetworkAccessManager(this);
- 1
查看官方文档可以知道,doWork槽函数会在另外一个线程被执行。这里
有new操作,而且传递了this指针,而且我们也可以从打印信息可知道此时this指针和doWorkA()不在同一线程,所以会报出错误:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is WorkerA(0x4558a8), parent's thread is QThread(0x4482e8), current thread is QThread(0x28fe1c)
- 1
- 2
解决办法是:
(1). new时不传递this指针
m_net2 = new QNetworkAccessManager;
- 1
(2). 将new操作放在WorkerA的构造函数中
m_net1 = new QNetworkAccessManager(this);
m_net2 = new QNetworkAccessManager(this);
- 1
- 2
- 3
(3).使用信号与槽的方法调用doWorkA()
总结
QObject: Cannot create children for a parent that is in a different thread.
- 1
这样的错误,多是由于在槽函数中多层嵌套时new操作出的问题,建议大家尽量避免在槽函数中进行new操作。
相关文章
- 解决Maven打包时报错"The packaging for this project did not assign a file to the build artifact"
- 【JAVA】Eclipse中开启java和xml智能提示功能(图文,已解决!)
- SQL“除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效“ 解决方法
- mysql出现“ You can't specify target table '表名' for update in FROM clause”解决方法
- mysql (已解决)Access denied for user 'root'@'localhost' (using password: NO)
- PID file /run/zabbix/zabbix_server.pid not readable (yet?) after start. 报错解决
- 为什么加了jquery mobile 会有 Loading 字样在页面底部?【已解决】
- 解决"No toolchains found in the NDK toolchains folder for ABI with prefix: mips64el-linux-android"错误
- this class is not key value coding-compliant for the key XXX错误的解决方法
- Access denied for user ‘root‘@‘% mysql在问题(解决)
- 解决docker容器映射信息修改问题
- 关于处理iis8.0中设置Request.BinaryRead 不允许操作的解决方法
- Mysql错误:Duplicate entry '127' for key 'PRIMARY'的解决方法
- 【快应用】text组件里的文字很多,旁边的div样式会被拉伸如何解决
- 我的Android进阶之旅------>解决:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
- Git for Windows之分支管理、分支合并、解决分支冲突
- 解决Manjaro linux的中文输入
- WPS for Linux提示“系统缺失字体symbol、wingdings、wingdings 2、wingdings 3、webding”的解决方法