PDA

View Full Version : Problems with QThread and QTcpSocket



cookiem
31st October 2006, 11:03
When socket writes data i get the "QObject: Cannot create children for a parent that is in a different thread." error, but the data is transferred anyway, because client gets it. QTcpSocket has no parent. Could someone help me in solving this? (Qt 4.2)

Here is the run():


void XRServerThread::run()
{
m_socket = new QTcpSocket;


//end if error occured
if(! m_socket->setSocketDescriptor(m_socket_descriptor))
{
//-32300 - xr transport error
emit error(XR_TRANSPORT_ERROR, QString("Socket error: %1")
.arg(m_socket->error()));
return;
}

connect(m_socket, SIGNAL(readyRead()), this, SLOT(readFromSocket()));
// connect(m_socket, SIGNAL(disconnected()), m_socket,
//SLOT(deleteLater()));
//exit the thread after disconnection
connect(m_socket, SIGNAL(disconnected()), this, SLOT(quit()));

//start event loop
exec();
}

.
.
.

Here is the place where error occurs (m_socket->write()):


void XRServerThread::sendHttpResponse(int status_code, const QString &reason,
QHttpHeader & headers, QString resp)
{
//This is the body of the response:
QByteArray output;
output.append(resp);

headers.setContentLength(output.size());

//This is the headers:
QByteArray head_out;
head_out.append(QString("HTTP/1.1 %1 %2\r\n")
.arg(QString::number(status_code)).arg(reason));
QStringList keys = headers.keys();

//creating string representation of headerss
foreach(QString key, keys)
{
head_out.append(QString("%1: %2\r\n").arg(key).arg(headers.value(key)));
}

head_out.append("\r\n");

//Write the headers out:
m_socket->write(head_out);

//Write the body out:
m_socket->write(output);

//Close the connection we will not write anything else
m_socket->disconnectFromHost();
m_socket->waitForDisconnected();
}

jpn
31st October 2006, 13:09
How does sendHttpResponse() get called? Most likely XRServerThread::sendHttpResponse() is executed in a different thread than what is being executed in XRServerThread::run(). An easy way to assure this is is to check QThread::currentThread() in both functions.

cookiem
31st October 2006, 14:04
Thanks! You're right it's called from different thread, but how to ensure that write() will be called from the same thread? Use QThreadStorage, or i don't get something?

Elgerton
1st November 2006, 15:42
How about sending a signal to the thread, so that sendHttpResponse is invoked via the event queue.

fullmetalcoder
1st November 2006, 22:00
Thanks! You're right it's called from different thread, but how to ensure that write() will be called from the same thread? Use QThreadStorage, or i don't get something?
I'm not sure but putting your code in another function which will be called from QThread::run() might help...

jpn
1st November 2006, 22:17
I never got an answer to my question, "How does sendHttpResponse() get called?" ..but anyway, I assume it gets called in consequence of the socket emitting a certain signal. Slots in a QThread object get executed in the thread where it lives in (that is the thread where it was created in), not in the thread which is being executed in QThread::run(). Check this thread (http://www.qtcentre.org/forum/f-qt-programming-2/t-non-gui-thread-blocking-gui-3848.html#14).

In my opinion the easiest solution would be to subclass QTcpSocket and write the functionality (which is currently in XRServerThread slots) into it. Then those slots would automatically get executed in correct thread.

cookiem
2nd November 2006, 09:25
I never got an answer to my question, "How does sendHttpResponse() get called?" ..but anyway, I assume it gets called in consequence of the socket emitting a certain signal. Slots in a QThread object get executed in the thread where it lives in (that is the thread where it was created in), not in the thread which is being executed in QThread::run(). Check this thread (http://www.qtcentre.org/forum/f-qt-programming-2/t-non-gui-thread-blocking-gui-3848.html#14).

In my opinion the easiest solution would be to subclass QTcpSocket and write the functionality (which is currently in XRServerThread slots) into it. Then those slots would automatically get executed in correct thread.

Oh, i am so sorry, i missed that. You are right it's called from a slot. Thanks for the link and everything else :) My question was answered! Thanks again!