Cannot create children for a parent that is in a different thread.
在Qt的官方文檔,你們知道有兩種方式使用 QThread。html
- 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這種方式時,常常會遇到下面相似的問題:c++
- QObject: Cannot create children for a parent that is in a different thread.
出現這樣的問題根本緣由就是,調用MoveToThread 以後,在 Worker的槽函數中Worker的私有成員中又進行了new操做,而且將this指針傳給了構造函數。看下實例:git
mainwindow.hgithub
#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.cppmarkdown
#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
程序運行輸出:ui
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()中this
m_net2 = new QNetworkAccessManager(this);
- 1
查看官方文檔能夠知道,doWork槽函數會在另一個線程被執行。這裏
有new操做,並且傳遞了this指針,並且咱們也能夠從打印信息可知道此時this指針和doWorkA()不在同一線程,因此會報出錯誤:spa
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操做。