Qt QThread 爬坑之旅(一)
来源:互联网 发布:vegas13是电脑软件 编辑:程序博客网 时间:2024/06/15 01:58
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_OBJECTpublic: explicit MainWindow(QWidget *parent = 0); ~MainWindow();signals: void doWorkSignal();private: Ui::MainWindow *ui; QThread m_thread; Worker m_worker;};#endif // MAINWINDOW_H
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();}
worker.h
#ifndef WORKER_H#define WORKER_H#include <QObject>#include <QThread>#include <QNetworkAccessManager>class WorkerA: public QObject{ Q_OBJECTpublic: 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_OBJECTpublic: explicit Worker(QObject *parent = 0); ~Worker();signals:public slots: void doWork();private: WorkerA *m_workerA;};#endif // WORKER_H
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;}
程序运行输出:
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)
在本案例中,Worker在槽函数中调用私有成员WorkerA的doWorkA(),doWorkA()中
m_net2 = new QNetworkAccessManager(this);
查看官方文档可以知道,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). new时不传递this指针
m_net2 = new QNetworkAccessManager;
(2). 将new操作放在WorkerA的构造函数中
m_net1 = new QNetworkAccessManager(this);m_net2 = new QNetworkAccessManager(this);
(3).使用信号与槽的方法调用doWorkA()
总结
QObject: Cannot create children for a parent that is in a different thread.
这样的错误,多是由于在槽函数中多层嵌套时new操作出的问题,建议大家尽量避免在槽函数中进行new操作。
测试代码:
https://github.com/RobinsonSir/QThreadTest1
0 0
- Qt QThread 爬坑之旅(一)
- Qt之线程(QThread)
- Qt之线程(QThread)
- Qt之线程(QThread)
- Qt自总结(一) QThread
- Qt之QThread(深入理解)
- Qt之QThread详解
- Qt之QThread
- Qt之QThread用法
- Qt之线程QThread
- Qt线程(QThread)
- QT之深入理解QThread
- qt多线程编程之QThread
- QT之深入理解QThread
- QT之QThread多线程编程
- qt线程 qthread(转)
- QT QThread
- Qt线程(QThread)的使用/简介
- eclipse --- 新建JSP页面默认模版设置
- uva 10008
- Scala Cookbook翻译 Chapter 2.Numbers 第一部分
- 【模拟】ECNA 2015 I What's on the Grille? (Codeforces GYM 100825)
- http协议简介
- Qt QThread 爬坑之旅(一)
- Comparator_Integer
- Leetcode 237. Delete Node in a Linked List
- Android自定义小星星评分控件
- Exception has been thrown by the target of an invocation 解决方案
- 解决开机密码问题。WINDOWS
- 【CSU1809】Parenthesis(线段树 + 贪心 + 前缀和)
- 使用Android系统自带的VpnService截取流量
- disconf 安装笔记