QThread 爬坑之旅(三种办法解决QObject: Cannot create children for a parent that is in a different thread)
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操作。
QThread 爬坑之旅(三种办法解决QObject: Cannot create children for a parent that is in a different thread)的更多相关文章
- java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁
多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 package thread_test; public class ThreadDemo1 extends ...
- 记一次项目使用webuploader爬坑之旅
因前端页面开发使用的为VUE开发,又要支持IE9,遂只有基于webuploader封装一个上传组件.地址:https://github.com/z719725611/vue-upload-web ...
- PHP修改memory_limit的三种办法
PHP修改memory_limit的三种办法 2010-06-11 10:57:11 分类: 可能是分词程序的问题.只要搜索的字段达到十个汉字以上,就会出现诸如以下的错误 Fatal error: ...
- 三种方法解决android帮助文档打开慢
三种方法解决android帮助文档打开慢 经查是因为本地文档中的网页有如下两段js代码会联网加载信息,将其注释掉后就好了 <link rel="stylesheet" h ...
- Oracle用户解锁的三种办法及默认的用户与密码
ORA-28000: the account is locked-的解决办法 2009-11-11 18:51 ORA-28000: the account is locked 第1步:使用PL/SQ ...
- 解决Viewpager满屏不能自适应填充内容的三种办法
由于排版问题,本人博客园同名博文地址为:http://www.cnblogs.com/bill-technology/articles/3143667.html 很多Android开发者在使用View ...
- WEB项目会话集群的三种办法
web集群时session同步的3种方法 在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上, 如果session不同步的 ...
- 部署vc2008开发的程序(三种办法,但是我觉得这种办法最不好)
如果你编译了一个VC2008的默认的CRT/MFC的应用程序,如果目标部署电脑上没有安装相应的VC2008的动态库,当运行你的程序的时 个,会出现如下错误信息. 这是因为程序使用了基于VC2008 ...
- Android 再按一次退出程序三种办法
在Xamarin android中双击返回键退出程序的第一种做法 思路就是当用户按下返回键的时间超过两秒就退出,根据Keycode.Back判断用户按下的是返回键,重写这个OnKeyDown Date ...
随机推荐
- kali(Ubuntu)右键添加idle打开方式
IDLE可以说是Unix平台下Python的第一个集成开发环境(IDE) 命名行输入idle看idle是否已安装,没有则先安装 安装idle:apt-get install idle 安装完成后,命名 ...
- 栈(stack)--c实现(使用双链表)
是不是直接贴代码不太好,我竟然不知道说什么. 写这个考虑的问题,或者是纠结的问题是这个头指针怎么处理,也就是栈的顶部,最后采用的是初始化第一个栈空间浪费掉,栈顶是有元素的.好像应该去学习下画图,没图不 ...
- 使用systemctl自定义系统服务
1.创建系统服务文件,格式如下: [Unit] Description=httpd After=network.target [Service] Type=forking ExecStart=/usr ...
- Docker之Mysql安装及配置
原文:Docker之Mysql安装及配置 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zhaobw831/article/details/8014 ...
- HDU 4756 Install Air Conditioning(次小生成树)
题目大意:给你n个点然后让你求出去掉一条边之后所形成的最小生成树. 比較基础的次小生成树吧. ..先prime一遍求出最小生成树.在dfs求出次小生成树. Install Air Conditioni ...
- 使用IR2101半桥驱动电机的案例
作为一个电机驱动开发方面的菜鸟,近日研究了一下通过MOS管对整流后的电源斩波用以驱动直流电机进行调速的方案. 在驱动的过程中,遇到了很多问题,当然也有很多的收获. 写下来以供自己将来查阅,也为其他菜鸟 ...
- python之路-------字符串与正則表達式
1.1.#####去掉字符串中的转义符string.strip() print "hello\tworld\n" >>> word="\thello w ...
- hdu1978 How many ways
How many ways Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 机器人一开始在棋 ...
- Metasploit的攻击实例讲解----辅助扫描工具
不多说,直接上干货! 怎么弹出来这个呢,连续按两次tab. msf > use auxiliary/scanner/ Display all possibilities? (y or n) us ...
- MyBatis、JDBC、Hibernate区别
从层次上看,JDBC是较底层的持久层操作方式,而Hibernate和MyBatis都是在JDBC的基础上进行了封装使其更加方便程序员对持久层的操作. 从功能上看, JDBC就是简单的建立数据库连接,然 ...