January 21, 2012

ryadav ryadav
Lab Rat
70 posts

[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:

  1. class TCPServer : public QThread
  2. {
  3.     Q_OBJECT
  4. public:
  5. ...
  6. signals:
  7.     void postTestResult( const std::string msg );
  8.  
  9. public slots:
  10.     void startServer();
  11.     void handleClientRequest();
  12. };
  13.  
  14. TCPServer::TCPServer(UnitTestMonitorDialog *parent) :
  15.     QThread(parent)
  16. {
  17.     m_pParent = parent;
  18.     connect( parent, SIGNAL(startServer()), this, SLOT(startServer()));
  19. }
  20.  
  21. void TCPServer::run()
  22. {
  23.     // enter message loop
  24.     exec();
  25. }
  26.  
  27. void TCPServer::startServer()
  28. {
  29.     // create listener socket and blocks on accept
  30.     // this is where my main gui thread blocks
  31. }
  32.  
  33. // my dialog app code create the worker thread and then starts it
  34.  
  35.     m_tcpServer = new TCPServer(this);
  36.  
  37.     connect( m_tcpServer, SIGNAL(postTestResult(std::string)), this, SLOT(postTestResult(std::string)) );
  38.    
  39.     m_tcpServer->start();
  40.  
  41.     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 QTMultiOutput

git clone git@gitorious.org:qt-samples/qt-samples.git

 Signature 

Kind Regards,
Rajinder Yadav

SafetyNet Test Driven Development
http://safetynet.devmentor.org

5 replies

January 21, 2012

koahnig koahnig
Area 51 Engineer
2893 posts

I am not an expert in threading, but the exec() in run() looks a bit suspicious to me. I do not think that you need to call exec() there.

January 21, 2012

ryadav ryadav
Lab Rat
70 posts

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.

 Signature 

Kind Regards,
Rajinder Yadav

SafetyNet Test Driven Development
http://safetynet.devmentor.org

January 21, 2012

Gerolf Gerolf
Robot Herder
3252 posts

According to the wiki Entry of peppe [developer.qt.nokia.com] 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.

 Signature 

Nokia Certified Qt Specialist.
Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

January 21, 2012

ryadav ryadav
Lab Rat
70 posts

OK after reading the wiki I made the following adjustment.

class TCPServer : public QObject

My main thread now does:

  1.     m_pServerThread = new QThread;
  2.     m_tcpServer = new TCPServer;
  3.  
  4.     connect( m_pServerThread, SIGNAL(started()), m_tcpServer, SLOT(startServer()) );
  5.  
  6.     m_tcpServer->moveToThread( m_pServerThread );
  7.     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!

 Signature 

Kind Regards,
Rajinder Yadav

SafetyNet Test Driven Development
http://safetynet.devmentor.org

January 22, 2012

ryadav ryadav
Lab Rat
70 posts

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

 Signature 

Kind Regards,
Rajinder Yadav

SafetyNet Test Driven Development
http://safetynet.devmentor.org

 
  ‹‹ compare QRadioButtons      Feedback on my idea of a new Function for the QString class ››

You must log in to post a reply. Not a member yet? Register here!