Unsolved QTcpSocket does not detect disconnect when created from worker thread
-
I am trying to use a QTcpSocket from a worker thread like in this example http://doc.qt.io/qt-5/qtnetwork-blockingfortuneclient-example.html
The socket connects properly.
However it fails to detects when the host disconnects. So the thread remains stuck in the loop.
If i create the socket in the main thread, it detects the disconnection properly.
class ClientThread : public QThread
{
Q_OBJECTpublic: ClientThread(QObject *parent = 0) {}; ~ClientThread() {}; void run() Q_DECL_OVERRIDE;
};
void ClientThread::run()
{
QTcpSocket socket;
socket.connectToHost(SERVER, PORT);if (socket.waitForConnected(TIMEOUT)) { // sleep as long as connected while(socket.state() == QAbstractSocket::SocketState::ConnectedState) { QThread::msleep(10); } // should exit here when host disconnects QThread::msleep(10); }
}
// from Main thread I call this
client_thread.start();Why is that?
-
@Milo
Did you check if it detects the dsiconnect when in main thread?AFAIK there might be a long timeout until the state is changed. I am checking the write to the host does not send all data respectively no data.
-
Yes I did.
if I run the following on the main thread, I exit the loop right when I close the server.
QTcpSocket socket;
socket.connectToHost(SERVER, PORT);if (socket.waitForConnected(TIMEOUT))
{
// sleep as long as connected
while(socket.state() == QAbstractSocket::SocketState::ConnectedState)
{
QThread::msleep(10);
}// should exit here when host disconnects QThread::msleep(10);
}
}
-
from
client_thread.start();
I see the thread is created on the stack, are you sure it does not go out of scope? QThread::start does not block the main thread.Could you show us the method where you call start() or try making client_thread a pointer to ClientThread and do
client_thread=new ClientThread; connect(client_thread,&ClientThread::finished,client_thread,&ClientThread::deleteLater); client_thread->start();
P.S.
When reimplementing any QObject you should always call the base class constructor to avoid breaking Qt parent-child system
ClientThread(QObject *parent = 0) {};
should become
ClientThread(QObject *parent = 0) :QThread(parent){};
-
sure @VRonin
client_thread is a member of a class deriving from QDialog.
I call client_thread.start() start from a button slot. -
@Milo
This code can't work simply because events are not processed for the thread. This means allQSocketNotifiers
are stuck and the state can't be changed because of the endless loop. Change that or use the async API.@VRonin
Additional implication of the above is that you can't have signals emitted from other threads execute slots in the current (when connected with Qt::QueuedConnection/Qt::AutoConnection/Qt::BlockingQueuedConnection).