Results 1 to 10 of 10

Thread: signals/slots across threads

  1. #1
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default signals/slots across threads

    Hi,

    Qt4.2.2 on linux.
    I have implemented a threaded communication scheme, but the slots of a non gui thread class are executed in the GUI thread.
    I was hoping maybe some one here could point to my mistake.
    Here is what I did in meta code, after the code a text explaining the behavior:
    Qt Code:
    1. //Base socket thread class
    2. class SocketThread : public QThread
    3. {
    4. Q_OBJECT
    5. protected:
    6. QTcpSocket *m_socket;
    7. QString m_host;
    8. quint32 m_port;
    9. QMutex m_socketMutex;
    10. QDataStream *m_dataStream;
    11. public:
    12. SocketThread(QString host,quint32 port,QObject *parent = 0);
    13.  
    14. ~SocketThread();
    15. const QDataStream & stream();
    16. void run();
    17. public slots:
    18. virtual void readSocket();
    19. };
    20.  
    21. void SocketThread::run()
    22. {
    23. if(!m_socket)
    24. {
    25. m_socket = new QTcpSocket();
    26. if(m_socket) m_dataStream = new QDataStream(m_socket);
    27. connect(m_socket,SIGNAL(readyRead()),this,SLOT(readSocket()));
    28. if(m_socket) m_socket->connectToHost(m_host,m_port);
    29. }
    30. exec();
    31. }
    32.  
    33. //Actual working class
    34. class HPSCSocket : public SocketThread
    35. {
    36. Q_OBJECT
    37. public:
    38. HPSCSocket(QString host,quint32 port,QObject *parent = 0);
    39.  
    40. ~HPSCSocket();
    41. signals:
    42. void sig_hpscReadout(int,float,float);
    43. public slots:
    44. void sendHPSCCommand(HPSC_Command cmd,long usWait);
    45. void readSocket();
    46.  
    47. };
    48.  
    49. void HPSCSocket::sendHPSCCommand(HPSC_Command cmd,long usWait=0)
    50. {
    51. qDebug()<<"HPSCSocket::sendHPSCCommand";
    52. if(m_dataStream)
    53. {
    54. qDebug()<<"sending command";
    55. *m_dataStream<<cmd;
    56. m_socket->flush();
    57. qDebug()<<"about to sleep "<<usWait;
    58. usleep(usWait);
    59. qDebug()<<"woke up";
    60. }
    61. }
    62.  
    63. //the class (GUI) that communicates through the threaded socket class HPSCSocket
    64. FrmPower::FrmPower(BUS bus1,BUS bus2,QWidget *parent)
    65. : QWidget(parent)
    66. {
    67. m_hpscSocket = new HPSCSocket(m_hpscHost.toString(),m_hpscPort,this);
    68. connect(this,SIGNAL(sig_hpscCommand(HPSC_Command,long)),m_hpscSocket,SLOT(sendHPSCCommand(HPSC_Command,long)),Qt::QueuedConnection);
    69. connect(m_hpscSocket,SIGNAL(sig_hpscReadout(int,float,float)),this,SLOT(hpscReadout(int,float,float)));
    70. }
    71.  
    72. void FrmPower::bus1()
    73. {
    74. command.cmd = SETCURR1;
    75. command.var = m_src1a;
    76. emit sig_hpscCommand(command,120000);
    77. }
    To copy to clipboard, switch view to plain text mode 

    As you can see, a socket is created in its own thread (not the GUI thead) in SocketThread::run().
    The GUI class FrmPower has a member variable of type HPSCSocket which is a subclass of the SocketThread class.
    The aim of this scheme, is to allow FrmPower to send information through the threaded socket as can be seen in FrmPower::bus1().
    (The reason is, that after each socket transmition there is a need for various sleep intervals, which would freeze the GUI thread, and other problems as well)
    The problem is, that although the socket is created in seperate thread to the GUI thread, the execution of HPSCSocket::sendHPSCCommand() happens in the main GUI thread, and I have no idea why.
    In addition, the output:
    QSocketNotifier: socket notifiers cannot be enabled from another thread
    comes out in HPSCSocket::sendHPSCCommand on the socket operations, but code runs, just not in the right thread.
    If any one could point me to my mistake it will be very appreciated.
    I didn't insert code that is not relevant for illustrating the problem, such as proper constructors , mutextes etc.

    Thanks in advance!

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: signals/slots across threads

    This has been discussed several times. QThread object lives in the thread that created it, but objects created in run() live in a new thread. You have to add Qt::DirectConnection to your connect statements.

    Qt Code:
    1. connect( m_socket, SIGNAL(readyRead()), this, SLOT(readSocket()), Qt::DirectConnection );
    To copy to clipboard, switch view to plain text mode 

  3. #3
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: signals/slots across threads

    Hi Jacek,

    thanks for the fast reply.
    QThread object lives in the thread that created it, but objects created in run() live in a new thread. You have to add Qt:irectConnection to your connect statements.
    I know, and I did(or at least its was what I think I did ), which is why I don't understand why the slot is executed in the GUI thread.
    My SocketThread derived class variable is created in a run() method, so it lives in its own thread right?
    So why his slots are executed in the main thread?

  4. #4
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: signals/slots across threads

    I am not interested in DirectConnection - that is the whole idea of having the thread for.
    I want to post the signals, and let the target thread execute them in its own time.

  5. #5
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: signals/slots across threads

    Hi Dani, nice to hear from you again I hope we can drink a 3EUR worth small bottle of water some time soon

    About the problem - as Jacek pointed out the problem of thread affinity causes Qt to misinterpret your intentions. HSCSocket (thread) is created with the GUI thread affinity and you then make a connection to the thread object that is handled by the GUI thread.
    There are two solutions:
    1. make the connection not to the thread object, but to an object created by the thread's run method
    or
    2. push the thread object to the thread itself, like so:
    Qt Code:
    1. connect(m_hpscSocket, SIGNAL(started()), this, SLOT(onStarted()));
    2. m_hpscSocket->start();
    3. //...
    4. void FrmPower::onStarted(){
    5. m_hpscSocket->moveToThread(m_hpscSocket);
    6. }
    To copy to clipboard, switch view to plain text mode 
    That just might work

    Remember you'll lose the parent-child relation between FrmPower object and the thread object.

  6. The following user says thank you to wysota for this useful post:

    babu198649 (12th October 2009)

  7. #6
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    5,372
    Thanks
    28
    Thanked 976 Times in 912 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11 Windows

    Default Re: signals/slots across threads

    Quote Originally Posted by theLSB View Post
    My SocketThread derived class variable is created in a run() method, so it lives in its own thread right?
    Yes, but "this" (i.e. SocketThread) lives in the GUI thread, because it was created there.

    Quote Originally Posted by theLSB View Post
    So why his slots are executed in the main thread?
    Because when you connect objects living in different threads (m_socket and "this") Qt by default creates a queued connection. Since "this" lives in the GUI thread, all meta call events will be queued by the GUI thread.

    Quote Originally Posted by theLSB View Post
    I want to post the signals, and let the target thread execute them in its own time.
    In that case you need two objects: a socket and a handler.
    Qt Code:
    1. void SocketThread::run()
    2. {
    3. if(!m_socket)
    4. {
    5. m_socket = new QTcpSocket();
    6. m_handler = new Handler( m_socket ); // <-- this object is responsible for reading data from the socket
    7. connect(m_socket,SIGNAL(readyRead()),handler,SLOT(readSocket()), Qt::QueuedConnection);
    8. ...
    9. }
    10. exec();
    11. }
    To copy to clipboard, switch view to plain text mode 
    In this case all meta call events will be queued by the SocketThread, but it really doesn't change much. You will still have one thread that reads data from the socket --- it will just do it in a bit different way.

    If you want to have two threads, you need one that will contain the socket and will be responsible for appending the received data to a buffer (queue?) and another one that will analyze that data and remove it from the buffer.

  8. The following 2 users say thank you to jacek for this useful post:

    babu198649 (12th October 2009)

  9. #7
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: signals/slots across threads

    Hi Wysota and Jacek,

    Yes, it will be cool to have a 3EU drink again, I wont mind if it will be a trolltech event though
    Ok, I think I understand now.
    Hmm, I new I need to implement a queue, and I thought that if I use the thread safe signal/slots I will just let the QThread queue do the work, and all I need to do is post signals from my gui thread.
    That was what I was trying to do anyhow...
    But you are right, my SocketThread class it self lives in the GUI thread.
    I guess I will just fall back to custom events then.
    I guess that the threaded signals/slots are doing just that behind the scenes, but for me it will be less coding with custom events.

    Thanks again for the first class help guys!

  10. #8
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: signals/slots across threads

    If you want a queue, maybe it's better to use postEvent() directly? Signals/slots won't give you any advantage here...

  11. The following user says thank you to wysota for this useful post:


  12. #9
    Join Date
    Jan 2006
    Location
    Munich, Germany
    Posts
    4,714
    Thanks
    21
    Thanked 418 Times in 411 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows

    Default Re: signals/slots across threads

    Yes, its exactly what I meant when I said custom events.
    Thanks.

  13. #10
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: signals/slots across threads

    Yes, I know I just noticed that after sending my post and added the second sentence just to make the post say something anyway

Similar Threads

  1. Querying within Threads
    By bera82 in forum Qt Programming
    Replies: 11
    Last Post: 12th March 2008, 01:08
  2. question about socket and threads?
    By oob2 in forum Qt Programming
    Replies: 2
    Last Post: 27th February 2007, 11:42
  3. Once more: Threads in Qt4
    By high_flyer in forum Qt Programming
    Replies: 5
    Last Post: 9th August 2006, 18:35
  4. Replies: 16
    Last Post: 7th March 2006, 15:57
  5. [QT4] threads, signals, and slots, please help.
    By ucntcme in forum Qt Programming
    Replies: 12
    Last Post: 25th January 2006, 14:23

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.