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操作。

测试代码: 
https://github.com/RobinsonSir/QThreadTest1

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zbc415766331/article/details/52462118
 
其实还是第四种做法,就是把WorkerA再次moveToThread一下,毕竟它是在构造函数里创建的,而那时候Worker所在的线程还是主线程。

QThread 爬坑之旅(三种办法解决QObject: Cannot create children for a parent that is in a different thread)的更多相关文章

  1. java——多线程的实现方式、三种办法解决线程赛跑、多线程数据同步(synchronized)、死锁

    多线程的实现方式:demo1.demo2 demo1:继承Thread类,重写run()方法 package thread_test; public class ThreadDemo1 extends ...

  2. 记一次项目使用webuploader爬坑之旅

       因前端页面开发使用的为VUE开发,又要支持IE9,遂只有基于webuploader封装一个上传组件.地址:https://github.com/z719725611/vue-upload-web ...

  3. PHP修改memory_limit的三种办法

     PHP修改memory_limit的三种办法 2010-06-11 10:57:11 分类: 可能是分词程序的问题.只要搜索的字段达到十个汉字以上,就会出现诸如以下的错误 Fatal error: ...

  4. 三种方法解决android帮助文档打开慢

    三种方法解决android帮助文档打开慢   经查是因为本地文档中的网页有如下两段js代码会联网加载信息,将其注释掉后就好了 <link rel="stylesheet" h ...

  5. Oracle用户解锁的三种办法及默认的用户与密码

    ORA-28000: the account is locked-的解决办法 2009-11-11 18:51 ORA-28000: the account is locked 第1步:使用PL/SQ ...

  6. 解决Viewpager满屏不能自适应填充内容的三种办法

    由于排版问题,本人博客园同名博文地址为:http://www.cnblogs.com/bill-technology/articles/3143667.html 很多Android开发者在使用View ...

  7. WEB项目会话集群的三种办法

    web集群时session同步的3种方法 在做了web集群后,你肯定会首先考虑session同步问题,因为通过负载均衡后,同一个IP访问同一个页面会被分配到不同的服务器上, 如果session不同步的 ...

  8. 部署vc2008开发的程序(三种办法,但是我觉得这种办法最不好)

    如果你编译了一个VC2008的默认的CRT/MFC的应用程序,如果目标部署电脑上没有安装相应的VC2008的动态库,当运行你的程序的时 个,会出现如下错误信息.   这是因为程序使用了基于VC2008 ...

  9. Android 再按一次退出程序三种办法

    在Xamarin android中双击返回键退出程序的第一种做法 思路就是当用户按下返回键的时间超过两秒就退出,根据Keycode.Back判断用户按下的是返回键,重写这个OnKeyDown Date ...

随机推荐

  1. kali(Ubuntu)右键添加idle打开方式

    IDLE可以说是Unix平台下Python的第一个集成开发环境(IDE) 命名行输入idle看idle是否已安装,没有则先安装 安装idle:apt-get install idle 安装完成后,命名 ...

  2. 栈(stack)--c实现(使用双链表)

    是不是直接贴代码不太好,我竟然不知道说什么. 写这个考虑的问题,或者是纠结的问题是这个头指针怎么处理,也就是栈的顶部,最后采用的是初始化第一个栈空间浪费掉,栈顶是有元素的.好像应该去学习下画图,没图不 ...

  3. 使用systemctl自定义系统服务

    1.创建系统服务文件,格式如下: [Unit] Description=httpd After=network.target [Service] Type=forking ExecStart=/usr ...

  4. Docker之Mysql安装及配置

    原文:Docker之Mysql安装及配置 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/zhaobw831/article/details/8014 ...

  5. HDU 4756 Install Air Conditioning(次小生成树)

    题目大意:给你n个点然后让你求出去掉一条边之后所形成的最小生成树. 比較基础的次小生成树吧. ..先prime一遍求出最小生成树.在dfs求出次小生成树. Install Air Conditioni ...

  6. 使用IR2101半桥驱动电机的案例

    作为一个电机驱动开发方面的菜鸟,近日研究了一下通过MOS管对整流后的电源斩波用以驱动直流电机进行调速的方案. 在驱动的过程中,遇到了很多问题,当然也有很多的收获. 写下来以供自己将来查阅,也为其他菜鸟 ...

  7. python之路-------字符串与正則表達式

    1.1.#####去掉字符串中的转义符string.strip() print "hello\tworld\n" >>> word="\thello w ...

  8. hdu1978 How many ways

    How many ways Problem Description 这是一个简单的生存游戏,你控制一个机器人从一个棋盘的起始点(1,1)走到棋盘的终点(n,m).游戏的规则描述如下: 机器人一开始在棋 ...

  9. Metasploit的攻击实例讲解----辅助扫描工具

    不多说,直接上干货! 怎么弹出来这个呢,连续按两次tab. msf > use auxiliary/scanner/ Display all possibilities? (y or n) us ...

  10. MyBatis、JDBC、Hibernate区别

    从层次上看,JDBC是较底层的持久层操作方式,而Hibernate和MyBatis都是在JDBC的基础上进行了封装使其更加方便程序员对持久层的操作. 从功能上看, JDBC就是简单的建立数据库连接,然 ...