QObject: Cannot create children for a parent that is in a different thread
-
In my main application thread:
ConnectionToTrainer* pConn(new ConnectionToTrainer( socketDescriptor, this)); QObject::connect(pConn, &ConnectionToTrainer::tcpReceived, this, &TcpBinaryReceiver::onTcpReceived); QObject::connect(qApp, &QCoreApplication::aboutToQuit, pConn, &ConnectionToTrainer::quit); QObject::connect(pConn, &ConnectionToTrainer::finished, pConn, &ConnectionToTrainer::deleteLater); pConn->start();The prototype for the class:
class ConnectionToTrainer : public QThread { Q_OBJECT private: QFile* mpobjRxFile; QTcpSocket* mpsckCli; qintptr msckDescriptor; QTimer mtmrRxEnd; quint32 muint32PacketNo; quint64 muint64Received; public: static const quint16 mscuint16RxEndTimeout; explicit ConnectionToTrainer(qintptr ID, QObject* pParent = nullptr); void kick(); void run(); signals: void error(QTcpSocket::SocketError sckError); void tcpReceived(qintptr msckDescriptor, quint32 uint32PacketNo, int intReceived); public slots: void disconnected(); void readyRead(); };And the implementation:
ConnectionToTrainer::ConnectionToTrainer(qintptr ID, QObject* pParent) : QThread(pParent), mpobjRxFile(nullptr), mpsckCli(nullptr), msckDescriptor(ID), muint32PacketNo(0), muint64Received(0) { QObject::connect(&mtmrRxEnd, &QTimer::timeout, [this]() { if ( muint64Received > 0 ) { //File received DatasetTransfer* pobjTransfer(DatasetTransfer::pCurrentTransfer()); if ( pobjTransfer != nullptr ) { QFile& rFile(pobjTransfer->rFile()); emit pobjTransfer->transferComplete(rFile.fileName()); } } mtmrRxEnd.stop(); } ); }At runtime I am seeing:
QObject: Cannot create children for a parent that is in a different thread. (Parent is ConnectionToTrainer(0x11d2d38), parent's thread is QThread(0x118a718), current thread is ConnectionToTrainer(0x11d2d38) I'm not exactly sure what this is telling me or what the offending code is or how to resolve? -
use worker and move the thread into the worker. Do not use qthread directly.
And send signal to the worker for creating children.
https://wiki.qt.io/QThreads_general_usage -
QThreadis not the secondary thread, it's a wrapper around it. onlyQThread::runis the secondary thread. slots ofQThreadwill be run in the main thread. see https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ -
use worker and move the thread into the worker. Do not use qthread directly.
And send signal to the worker for creating children.
https://wiki.qt.io/QThreads_general_usage -
In my main application thread:
ConnectionToTrainer* pConn(new ConnectionToTrainer( socketDescriptor, this)); QObject::connect(pConn, &ConnectionToTrainer::tcpReceived, this, &TcpBinaryReceiver::onTcpReceived); QObject::connect(qApp, &QCoreApplication::aboutToQuit, pConn, &ConnectionToTrainer::quit); QObject::connect(pConn, &ConnectionToTrainer::finished, pConn, &ConnectionToTrainer::deleteLater); pConn->start();The prototype for the class:
class ConnectionToTrainer : public QThread { Q_OBJECT private: QFile* mpobjRxFile; QTcpSocket* mpsckCli; qintptr msckDescriptor; QTimer mtmrRxEnd; quint32 muint32PacketNo; quint64 muint64Received; public: static const quint16 mscuint16RxEndTimeout; explicit ConnectionToTrainer(qintptr ID, QObject* pParent = nullptr); void kick(); void run(); signals: void error(QTcpSocket::SocketError sckError); void tcpReceived(qintptr msckDescriptor, quint32 uint32PacketNo, int intReceived); public slots: void disconnected(); void readyRead(); };And the implementation:
ConnectionToTrainer::ConnectionToTrainer(qintptr ID, QObject* pParent) : QThread(pParent), mpobjRxFile(nullptr), mpsckCli(nullptr), msckDescriptor(ID), muint32PacketNo(0), muint64Received(0) { QObject::connect(&mtmrRxEnd, &QTimer::timeout, [this]() { if ( muint64Received > 0 ) { //File received DatasetTransfer* pobjTransfer(DatasetTransfer::pCurrentTransfer()); if ( pobjTransfer != nullptr ) { QFile& rFile(pobjTransfer->rFile()); emit pobjTransfer->transferComplete(rFile.fileName()); } } mtmrRxEnd.stop(); } ); }At runtime I am seeing:
QObject: Cannot create children for a parent that is in a different thread. (Parent is ConnectionToTrainer(0x11d2d38), parent's thread is QThread(0x118a718), current thread is ConnectionToTrainer(0x11d2d38) I'm not exactly sure what this is telling me or what the offending code is or how to resolve?@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
At runtime I am seeing:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is ConnectionToTrainer(0x11d2d38), parent's thread is QThread(0x118a718), current thread is ConnectionToTrainer(0x11d2d38)I'm not exactly sure what this is telling me or what the offending code is or how to resolve?
Once again you done same mistake.
QThreadis aQObjectbased class which contains/manage a thread.
The instance ofQThread'lives' in the thread in which it was created, which is not the same as the contained thread!So please avoid to sub-class QThread if you want to use it with QObjects and/or signals/slots and use a worker class which you moves to the dedicated thread.
-
@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
At runtime I am seeing:
QObject: Cannot create children for a parent that is in a different thread.
(Parent is ConnectionToTrainer(0x11d2d38), parent's thread is QThread(0x118a718), current thread is ConnectionToTrainer(0x11d2d38)I'm not exactly sure what this is telling me or what the offending code is or how to resolve?
Once again you done same mistake.
QThreadis aQObjectbased class which contains/manage a thread.
The instance ofQThread'lives' in the thread in which it was created, which is not the same as the contained thread!So please avoid to sub-class QThread if you want to use it with QObjects and/or signals/slots and use a worker class which you moves to the dedicated thread.
@KroMignon , there are plenty of examples:
https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html
That show using QThread in the same way I have.
-
@KroMignon , there are plenty of examples:
https://doc.qt.io/qt-5/qtnetwork-threadedfortuneserver-example.html
That show using QThread in the same way I have.
@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
That show using QThread in the same way I have.
No really as you are doing.
Is this example,QThread::run()is overriding and all QObject based instances are created there. So they are all living in the holded thread.
Your are creating aQTimerwithinConnectionToTrainerconstructor, so this timer is living the same thread which have be used to createConnectionToTrainerinstance. Which is, obviously, not the same as the managed thread. -
@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
That show using QThread in the same way I have.
No really as you are doing.
Is this example,QThread::run()is overriding and all QObject based instances are created there. So they are all living in the holded thread.
Your are creating aQTimerwithinConnectionToTrainerconstructor, so this timer is living the same thread which have be used to createConnectionToTrainerinstance. Which is, obviously, not the same as the managed thread.@KroMignon , I'll try to describe the problem.
I have an application 'server' that is the focal point for other 'client' applications. The server uses UDP to communicate with all clients notifying them that content is ready.
Once a client receives the broadcast via UDP it sends a request to the server for the content. The content is then sent via TCP. I have a thread that creates a TCP connection to the client and sends the file over TCP, what I want to do is get the client to wait until the file transfer completes. I use a timer in the client to determine when the data flow from the server has ended. The server sends binary data and in some cases this can be over 1GB.
In the client class that receives the TCP data I have a thread that updates the GUI whilst the transfer is in progress. So I have modified the run function to loop whilst the timer isActive, what do I need to do in the loop to ensure that application functions correct, what is the correct way to satisfy this ?
-
@KroMignon , I'll try to describe the problem.
I have an application 'server' that is the focal point for other 'client' applications. The server uses UDP to communicate with all clients notifying them that content is ready.
Once a client receives the broadcast via UDP it sends a request to the server for the content. The content is then sent via TCP. I have a thread that creates a TCP connection to the client and sends the file over TCP, what I want to do is get the client to wait until the file transfer completes. I use a timer in the client to determine when the data flow from the server has ended. The server sends binary data and in some cases this can be over 1GB.
In the client class that receives the TCP data I have a thread that updates the GUI whilst the transfer is in progress. So I have modified the run function to loop whilst the timer isActive, what do I need to do in the loop to ensure that application functions correct, what is the correct way to satisfy this ?
@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
what is the correct way to satisfy this ?
I am not a C++/Qt expert, so I avoid to do "fancy stuff".
I am always usingQObjectbased worker classes to handle the task I have to do. When multi-threading is required, I don't have to change anything in my code, only have to add amoveToThread()call to use a dedicated thread for this task.
Of course, there are some rules to follow:- all children must have base instance as parent to "follow" the parent in the new thread or create all children instances in a kind of "start()" function which is called from the new thread (as described here: https://wiki.qt.io/QThreads_general_usage)
- use signals and slots to communicate with outside to avoid threading issues and let Qt handle this for you (I am lazy!)
So based on this, I would create a worker class which handles the socket and emits a signal to notify about transfer progression (eg.
progress(int prct)). And use this signal to update the GUI. -
@KroMignon , I'll try to describe the problem.
I have an application 'server' that is the focal point for other 'client' applications. The server uses UDP to communicate with all clients notifying them that content is ready.
Once a client receives the broadcast via UDP it sends a request to the server for the content. The content is then sent via TCP. I have a thread that creates a TCP connection to the client and sends the file over TCP, what I want to do is get the client to wait until the file transfer completes. I use a timer in the client to determine when the data flow from the server has ended. The server sends binary data and in some cases this can be over 1GB.
In the client class that receives the TCP data I have a thread that updates the GUI whilst the transfer is in progress. So I have modified the run function to loop whilst the timer isActive, what do I need to do in the loop to ensure that application functions correct, what is the correct way to satisfy this ?
@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
what is the correct way to satisfy this
why don't you tell the receiver via UDP that the transfer is done. instead of an arbitrary waiting time?
-
@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
what is the correct way to satisfy this
why don't you tell the receiver via UDP that the transfer is done. instead of an arbitrary waiting time?
-
@SPlatten said in QObject: Cannot create children for a parent that is in a different thread:
@J-Hilk , thank you, I will give that a go, although the UDP goes to all clients.
I know, I usually have an ID - byte at the front of my UDP datagrams, that identifies it as a Datagram for all or for a specific recipient