[SOLVED] thread with signal and slots, my code seems to hang
-
Hi I have a simple tcp socket dialog app that creates a listener thread. I seem to have the signal and slots working across thread. however the main thread seems to block with i emit a signal to the worker thread.
I am not sure what i am doing wrong, here is basically my code:
@class TCPServer : public QThread
{
Q_OBJECT
public:
...
signals:
void postTestResult( const std::string msg );public slots:
void startServer();
void handleClientRequest();
};TCPServer::TCPServer(UnitTestMonitorDialog *parent) :
QThread(parent)
{
m_pParent = parent;
connect( parent, SIGNAL(startServer()), this, SLOT(startServer()));
}void TCPServer::run()
{
// enter message loop
exec();
}void TCPServer::startServer()
{
// create listener socket and blocks on accept
// this is where my main gui thread blocks
}// my dialog app code create the worker thread and then starts it
m_tcpServer = new TCPServer(this); connect( m_tcpServer, SIGNAL(postTestResult(std::string)), this, SLOT(postTestResult(std::string)) ); m_tcpServer->start(); emit startServer(); // <=== main thread hangs
@
My understanding is that when the worker thread is created it enter it's own message loop when it make a call to exec(), this allows for the cross thread signal / slots to work. But my code seems to be running like a single thread app, since the main ui thread end up getting blocked after the emit call.
What am I doing wrong?
Update
I created a sample showing the proper way to emit signals between threads, the source can be obtained using Git from GITORIOUS, see project folder QTMultiOutputgit clone git@gitorious.org:qt-samples/qt-samples.git
-
According to the doc, I am doing the right thing. http://doc.qt.nokia.com/4.8-snapshot/qthread.html#details.
without the call to exec(), the thread would exit and end! the call to exec() enter's a message loop, afaik the message loop is required for signal and slot to work across threads.
imho when you say something looks suspicious, you need to qualify your reason, otherwise it doesn't help.
-
According to "the wiki Entry of peppe":http://developer.qt.nokia.com/wiki/Threads_Events_QObjects and my knowledge, you are doing it wrong :-)
You connect to a signal that is part of the thread object. The thread object is running in the main thread, so the slot is executed in the main thread, not in the worker thread. Regard the thread object as thread administrator. You can (theoretically) move that thing to the thread itself, but that's IMHO no good design.
-
OK after reading the wiki I made the following adjustment.
class TCPServer : public QObject
My main thread now does:
@
m_pServerThread = new QThread;
m_tcpServer = new TCPServer;connect( m_pServerThread, SIGNAL(started()), m_tcpServer, SLOT(startServer()) ); m_tcpServer->moveToThread( m_pServerThread ); m_pServerThread->start();@
The worker thread is doing the blocking call and the main UI thread is handing it's message loop.
The problem now seem is that when the worker thread get some data, it needs to emit it over to the UI for displaying that data. Looks like worker's emit is getting made from the worker thread as a direct call, and afaik the worker thread can't make call to widgets. In short the UI does not get updated!
-
Gerolf thanks for the link it was helpful, I had to sleep on it and I finally got a working sample app to do things right.
If others are curious to see how, I created a sample showing the proper way to emit signals between threads, the source can be obtained using Git from GITORIOUS, see project folder QTMultiOutput
git clone git@gitorious.org:qt-samples/qt-samples.git
-
ryadav,
I am trying to do something very similar with Qt, but it doesn't look like your example is on gitorious any longer. Anyway you could post it somewhere?
-
ryadav,
I am trying to do something very similar with Qt, but it doesn't look like your example is on gitorious any longer. Anyway you could post it somewhere?