PDA

View Full Version : "Cannot create children for a parent that is in a different thread"



DiamonDogX
7th July 2009, 20:47
I have a class that inherits QThread designed to use a QTcpSocket to receive data from some server:


class ReceiveThread : public QThread
{
Q_OBJECT

public:
ReceiveThread( QHostAddress address, int port, QWidget * parent = 0 );
virtual ~ReceiveThread();

protected:
void run();

private:
QAbstractSocket * _socket;
QHostAddress _address;
int _port;
QTimer * _connectionAttemptTimer;
};

void ReceiveThread::run()
{
_connectionAttemptTimer->start(); // problem 1
_socket->connectToHost( _address, _port ); // problem 2
exec();
}

I also have a QWidget in which I want to use this class:


ConfigWidget::ConfigWidget( QWidget* parent ) : QWidget( parent ), _ui (new Ui_ConfigWidget())
{
_ui->setupUi( this );

_receiveThread = new ReceiveThread(
QHostAddress( "192.168.1.2" ), 9000 );

connect( _ui->testConnectionPushButton, SIGNAL( clicked() ),
this, SLOT( testConnectionPushButtonClicked() ) );
}

void ConfigWidget::testConnectionPushButtonClicked()
{
_receiveThread->start();
}

I basically get 2 errors when it executes the run() method of the QThread (marked above in the code):

QObject::startTimer: timers cannot be started from another thread
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QTcpSocket(0x2255780), parent's thread is QThread(0x2160250), current thread is ReceiveThread(0x224fe90)

I kind of understand... but not really...

caduel
7th July 2009, 20:59
Note that the QThread object (and all its member variables and all things created in your (subclass's) constructor belong to the thread the QThread object is created in.

Thus you get a "conflict" when you try to use those things from "your" thread.
One way to work around that is to created needed resources at the beginning of your thread's run() function.

be sure to read threads

HTH

DiamonDogX
7th July 2009, 21:13
I have read about threads on the link you sent.

I understand the timer thing, so I tired actually instantiating it in the run() method, which worked fine, but a problem I ran into was in my slot for its timeout() signal, in which I wish to call stop() on the timer. I get:

"QObject::killTimer: timers cannot be stopped from another thread"

-----------------------
EDIT: Hmm I actually got rid of that error by using "Qt::ConnectionType:: DirectConnection" in the connect call.

wysota
7th July 2009, 21:51
Of course you know that QTcpSocket works in asynchronous manner and you don't need a dedicated thread to use it, right?

DiamonDogX
7th July 2009, 22:04
Yes but I would prefer to encapsulate a lot of things in my thread class besides the QTcpSocket...

wysota
7th July 2009, 22:58
As for now you are making things harder than they could be. Especially that eventually you're running an event loop in the other thread so the only difference between this application and the application where you'd be doing everything in one thread is that... you have two threads. And the application becomes slower (with two threads instead of one) but let's ignore that for now.

DiamonDogX
8th July 2009, 13:24
I will definitely keep that in mind, thanks.