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 ...
随机推荐
- ajax请求携带 cookie
之前都有这样一个理解:ajax请求时是不会自动带上cookie的,要是想让他带上的话,必须哟啊设置withCredential为true.这个说法会让人产生完全扭曲的误解,我就是其中之一.完整的无歧义 ...
- PHP XML To Array将XML转换为数组
// Xml 转 数组, 包括根键,忽略空元素和属性,尚有重大错误 function xml_to_array( $xml ) { $reg = "/<(\\w+)[^>]*?& ...
- BZOJ 5394 [Ynoi2016]炸脖龙 (线段树+拓展欧拉定理)
题目大意:给你一个序列,需要支持区间修改,以及查询一段区间$a_{i}^{a_{i+1}^{a_{i+2}...}}mod\;p$的值,每次询问的$p$的值不同 对于区间修改,由线段树完成,没什么好说 ...
- react-native 运行提示红屏 error: bundling failed: ambiguous resolution: module `/User/xxx/Project/ico/index.js` tries to require `react-native`, but there are several files providing this module. You can de
运行 react-native start 报错 执行这2个进行清除缓存问题 yarn start -- --reset-cache npm start -- --reset-cache
- nessus 漏洞扫描安装和使用
介绍 Nessus 是目前全世界最多人使用的系统漏洞扫描与分析软件.总共有超过75,000个机构使用Nessus 作为扫描该机构电脑系统的软件. 软件特色 * 提供完整的电脑漏洞扫描服务, 并随时更 ...
- window安装特定补丁(勒索病毒)
最近出现震惊的蠕虫病毒(勒索病毒),微软也做出相应的安全补丁来修复 MS17-010.这时有些同学不想打开电脑 的自动更新,这样会下载大量补丁,要更新完这些补丁要好几个小时,为了不影响正常工作,我们就 ...
- Vue中如何监控某个属性值的变化?
比如现在需要监控data中, obj.a 的变化.Vue中监控对象属性的变化你可以这样: deep属性表示深层遍历,但是这么写会监控obj的所有属性变化,并不是我们想要的效果,所以做点修改: 还有一种 ...
- 【codeforces 255D】Mr. Bender and Square
[题目链接]:http://codeforces.com/problemset/problem/255/D [题意] 给你一个n*n的方框; 给你一个方块;(以下说的方块都是单位方块) 每一秒钟,可以 ...
- Tomcat连HBase报错: HTTP Status 500 - java.lang.AbstractMethodError: javax.servlet.jsp.JspFactory.getJspApplicationContext
Tomcat中连接HBase数据库,启动的时候报错: HTTP Status 500 - java.lang.AbstractMethodError: javax.servlet.jsp.JspFac ...
- [Transducer] Lazyness in Transduer
Transducers remove the requirement of being lazy to optimize for things like take(10). However, it c ...