QObject: cannot create child elements for a parent who is in another thread

EDIT:

I tried to do what you guys told me in the comments ...:

Citizen * c = new Citizen(this); QThread thread; c->moveToThread(&thread); connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions())); thread.start(); 

This causes even more errors:

 QThread: Destroyed while thread is still running ASSERT failure in QThread::setTerminationEnabled(): "Current thread was not started with QThread.", file c:\ndk_buildrepos\qt-desktop\src\corelib\thread\qthread_win.cpp, line 542 Invalid parameter passed to C runtime function. Invalid parameter passed to C runtime function. QObject::killTimers: timers cannot be stopped from another thread 

I am having problems with this error ... Iโ€™ve been stuck with this for 2 days and cannot get a solution.

Title:

 class Citizen : public QThread { Q_OBJECT QNetworkAccessManager * manager; private slots: void onReplyFinished(QNetworkReply* net_reply); public: Citizen(QObject * parent); void run(); }; 

Implementation:

 Citizen::Citizen(QObject * parent) { manager = new QNetworkAccessManager; connect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onReplyFinished(QNetworkReply*))); } void Citizen::onReplyFinished(QNetworkReply* net_reply) { emit onFinished(net_reply); } void Citizen::run() { manager->get(QNetworkRequest(QUrl("http://google.com")); QEventLoop eLoop; connect(manager, SIGNAL( finished( QNetworkReply * ) ), &eLoop, SLOT(quit())); eLoop.exec(QEventLoop::ExcludeUserInputEvents); qDebug() << "loaded google!"; exec(); } 

When manager-> get () starts, the following error appears:

 QObject: Cannot create children for a parent that is in a different thread. (Parent is QNetworkAccessManager(0xc996cf8), parent thread is QThread(0xaba48d8), current thread is Citizen(0xca7ae08) 

When eLoop.exec () is executed:

 QObject::startTimer: timers cannot be started from another thread 

I start this thread as follows:

 Citizen * c = new Citizen(this); c->start(); 

Why is this happening? How to solve this?

+7
source share
6 answers

I will just try to answer why you see QThread: Destroyed and the thread is still working .

If you do it

 void mtMethod () { Citizen * c = new Citizen(this); QThread thread; c->moveToThread(&thread); connect(&thread, SIGNAL(started()), c, SLOT(ProcessActions())); thread.start(); } 

The thread object will be destroyed when the function exits, but the thread that was started is still running! Qt warns you that you must either stop the stream or create a stream object in a larger volume. (i.e. make it a member function of your class). Something like that:

 class myClass { virtual ~myClass (); QThread mythread; }; myClass::~myClass { mythread.stop (); } void myClass::mtMethod () { Citizen * c = new Citizen(this); c->moveToThread(&mythread); connect(&mythread, SIGNAL(started()), c, SLOT(ProcessActions())); mythread.start(); } 
+3
source
 QObject: Cannot create children for a parent that is in a different thread. 

You get this because you create a QNetworkAccessmanager in the Citizen constructor, which is called in the "source" thread. When a Citizen object moves to a new stream, the QNetworkAccessmanager still has the flow affinity set in the original stream, but in a run call it will try to create a QNetworkReply object (and possibly other objects as well) in the new stream. Which issues the warning above.

If you create a manager in the execution slot (or at any time after moving the Citizen object to a new thread), this will not happen.

However, you still have some problems. For example, the Citizen class really should not be QThread. This complicates it uselessly. A subclass of QObject will suffice for your purpose (afaict). Just make a regular slot and connect it to the QThread :: start () signal. And, as OrcunC pointed out, you need to make sure that the QThread instance is correctly covered.

More on streaming: http://blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Example:

 QThread *thread = new QThread; thread->start(); Citizen *worker = new Citizen; worker->moveToThread(thread); //startWorking can be equivalent of the run function //in your current implementation and this is where you should //create the QNetworkAccessManager QMetaObject::invokeMethod(worker,"startWorking"); 
+10
source

I do not believe that a new thread exists before the run call. Thus, the constructor is a different thread than run (). What happens if you move the creation of the manager object from the constructor to run ()? I guess that will fix the first error, if not a timer error.

In addition, I think that many people are still building threads the way you are, but you can check this out .

+1
source

You need to consider the similarity of threads . This error message is not false or insane, and it tells you exactly what is wrong.

+1
source

Your problems are mainly related to trying to subclass QThread. Although the documentation recommends it, this is not the best way to use QThread. Please see this question and answer for more information and links.

+1
source

I did not understand the startTimers error, although this could be due to the first. In any case, you should be able to correct the first error. I encountered this problem in Qt several times, and I believe that this is the best way to get around this, to create an initialization function and a cleanUp function. All members of the class are pointers that are initialized to NULL until run is called. Please note that the "best" is in quotation marks, because there will certainly be different opinions, but it works for most situations for me.

Headline

 class Citizen : public QThread { Q_OBJECT QNetworkAccessManager * manager; private slots: void onReplyFinished(QNetworkReply* net_reply); public: Citizen(QObject * parent); void run(); private: void initialize(); void cleanUp(); }; 

Implementation

 Citizen::Citizen(QObject * parent) : manager(NULL) { } void Citizen::onReplyFinished(QNetworkReply* net_reply) { emit onFinished(net_reply); } void Citizen::run() { initialize(); manager->get(QNetworkRequest(QUrl("http://google.com")); QEventLoop eLoop; connect(manager, SIGNAL( finished( QNetworkReply * ) ), &eLoop, SLOT(quit())); eLoop.exec(QEventLoop::ExcludeUserInputEvents); qDebug() << "loaded google!"; exec(); cleanUp(); } void Citizen::initialize() { manager = new QNetworkAccessManager; connect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onReplyFinished(QNetworkReply*))); } void Citizen::cleanUp() { delete manager; disconnect(_net_acc_mgr, SIGNAL(finished(QNetworkReply*)), this, SLOT(onReplyFinished(QNetworkReply*))); } 
+1
source

All Articles