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 ...
随机推荐
- document.body
比如document.body,最好是写成document.getElementsByTagName("body")[0];
- MFC基础知识
1.句柄:具有内存后,系统返回的标识符 2.消息:相当于事件,例如鼠标点击就是一个消息 3.消息队列:就是将事件按照时间的先后顺序在一个队列中 4.消息处理机制:首先操作系统拿到消息,然后将消息放到消 ...
- 51nod 1526 分配笔名(Trie树+贪心)
建出Trie树然后求出一个点子树中有多少笔名和真名.然后贪心匹配即可. #include<iostream> #include<cstring> #include<cst ...
- 动态Axios配置
推荐使用Vue-cli工具来创建和管理项目,就算刚开始不熟悉,用着用着便可知晓其中的奥妙.前一段时间官方所推荐的数据请求插件还是Vue-resource,但现在已经变了,变成了Axios,不用知道为什 ...
- Java里的各种队列
以下翻译来自java8的官方文档: 1.LinkedBlockingQueue:基于链接节点的可选限定的blocking queue . 这个队列排列元素FIFO(先进先出). 队列的头部是队列中最长 ...
- 在android中,编译的项目使用到第三方jar的导入方法 终极版!
1,在android系统环境中编译自己的项目时,往往会用到第三方jar包.这些jar包在eclipse中加入编译,一路畅通,由于eclipse已经帮助你配置好了.可是当把这个项目复制到系统环境中编译时 ...
- MySQL 一台主机多实例root登录问题
假设在一台机子上起多个MySQL实例. 比方port号为 3306. 3307. 3308 登录时候要选择不同的 mysql.sock文件 mysql -uroot -p123456 这一句 登录的是 ...
- POJ 2110 二分+暴搜
题意: 给你一个矩阵 ,你能往各个方向走(不走出去就行),每次只能上下左右走一格,问路径上的点权最大值和最小值的差最小是多少. 思路: 首先 二分最后的答案, 暴力枚举当前的区间是啥. DFS 就OK ...
- 【DNN引用包】
<%@ Register TagPrefix="dnn" TagName="address" Src="~/controls/address.a ...
- Flume 启动
Configuration是Flume项目的入口程序了,当我们输入 bin/flume-ng agent --conf conf --conf-file conf/kafka1.properties ...