Results 1 to 4 of 4

Thread: Executing slots in a separate QThread?

  1. #1
    Join Date
    Oct 2009
    Posts
    33
    Thanks
    2

    Default Executing slots in a separate QThread?

    Hey all,

    I have a quick question regarding the start up of a new thread, separate to the main thread, and executing a slot in it, from a signal invoked from the main GUI thread. I understand this behaviour is not normally recommended.

    I created a simple subclass of QThread and connected a signal from my main thread to a slot in the subclassed thread. The slot prints out the current thread id. Initializing my class object in the main thread also prints out the current thread id. However, both these threads have the same id... aren't they supposed to be different? I'm using QThread::currentThread() to return the ID, and I read there might be issues using this with win32, but I'm on Linux. I've provided my source at the bottom of the post.

    ## output ##
    Qt Code:
    1. Main thread is 0x90fd250
    2. Executing Slot in 0x90fd250
    3. Executing Slot in 0x90fd250
    4. Executing Slot in 0x90fd250
    To copy to clipboard, switch view to plain text mode 

    If I move the thread object to the actual thread, (using moveToThread), the results are as expected:

    Qt Code:
    1. Main thread is 0x8ac5250
    2. Executing Slot in 0x8ace860
    3. Executing Slot in 0x8ace860
    4. Executing Slot in 0x8ace860
    To copy to clipboard, switch view to plain text mode 

    I just wanted to know if using moveToThread is the right way to do this (what if the thread quits or is terminated?)


    ## main.cpp ##
    Qt Code:
    1. #include <QtCore/QCoreApplication>
    2. #include "test.h"
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QCoreApplication a(argc, argv);
    7.  
    8. MyObject thisIsATest;
    9.  
    10. return a.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 


    ## test.h ##
    Qt Code:
    1. #include <new>
    2. #include <iostream>
    3. #include <iomanip>
    4. #include <stdlib.h>
    5. #include <vector>
    6. #include <time.h>
    7. #include <math.h>
    8. #include <fstream>
    9. #include <sstream>
    10. #include <stdexcept>
    11.  
    12. // Qt Includes
    13. #include <QThread>
    14. #include <QMutex>
    15. #include <QString>
    16. #include <QWaitCondition>
    17.  
    18. class MyObject;
    19. class MyThread;
    20.  
    21. class MyThread : public QThread
    22. {
    23. Q_OBJECT
    24.  
    25. public:
    26. MyThread(MyObject* ptr, QObject *parent = 0) { MyObjectPtr = ptr; }
    27. ~MyThread() {}
    28.  
    29. public slots:
    30. void MyThreadsStartup();
    31. void MyThreadsSlot();
    32.  
    33. protected:
    34. void run();
    35.  
    36. private:
    37. MyObject* MyObjectPtr;
    38.  
    39. };
    40.  
    41. class MyObject : public QObject
    42. {
    43. Q_OBJECT
    44.  
    45. public:
    46. MyObject(QObject *parent = 0);
    47. ~MyObject() {}
    48.  
    49. signals:
    50. void TriggerThread();
    51.  
    52. private:
    53. MyThread* myThread;
    54.  
    55. };
    To copy to clipboard, switch view to plain text mode 

    ## test.cpp ##
    Qt Code:
    1. #include "test.h"
    2.  
    3.  
    4. void MyThread::MyThreadsStartup()
    5. { QObject::connect(MyObjectPtr, SIGNAL(TriggerThread()), this, SLOT(MyThreadsSlot()));
    6. //moveToThread(this)
    7. }
    8.  
    9. void MyThread::MyThreadsSlot()
    10. { std::cerr << " Executing Slot in " << QThread::currentThread() << std::endl; }
    11.  
    12. void MyThread::run()
    13. { exec(); }
    14.  
    15.  
    16. MyObject::MyObject(QObject *parent) : QObject(parent)
    17. {
    18. std::cerr << " Main thread is " << QThread::currentThread() << std::endl;
    19. myThread = new MyThread(this);
    20. myThread->MyThreadsStartup();
    21. myThread->start();
    22.  
    23.  
    24. emit TriggerThread();
    25. emit TriggerThread();
    26. emit TriggerThread();
    27. }
    To copy to clipboard, switch view to plain text mode 

    Regards,

    -KF
    Last edited by kachofool; 9th December 2009 at 01:21.

  2. #2
    Join Date
    Sep 2009
    Location
    Tashkent, Uzbekistan
    Posts
    107
    Thanks
    1
    Thanked 4 Times in 4 Posts
    Qt products
    Qt4 Qt/Embedded
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: Executing slots in a separate QThread?

    Hi,

    just corrected your code a bit:

    Here it is results:
    ./threadtest
    Main thread is MyObject(0x7fff6d5b6280)
    Executing Slot in MyThread(0x60b9d0)
    Executing Slot in MyThread(0x60b9d0)
    Executing Slot in MyThread(0x60b9d0)
    Corrected code below:

    test.h

    Qt Code:
    1. // Qt Includes
    2. #include <QThread>
    3. #include <QMutex>
    4. #include <QString>
    5. #include <QWaitCondition>
    6.  
    7. class MyObject;
    8. class MyThread;
    9.  
    10. class MyThread : public QThread
    11. {
    12. Q_OBJECT
    13.  
    14. public:
    15.  
    16. MyThread(QObject *parent = 0) {}
    17. ~MyThread() {}
    18.  
    19. public slots:
    20.  
    21. void MyThreadsSlot();
    22. void refMyObject(MyObject* theValue);
    23.  
    24. protected:
    25. void run();
    26.  
    27. private:
    28.  
    29. MyObject* MyObjectPtr;
    30.  
    31. };
    32.  
    33. class MyObject : public QObject
    34. {
    35. Q_OBJECT
    36.  
    37. public:
    38. MyObject(QObject *parent = 0);
    39. ~MyObject() {}
    40.  
    41. signals:
    42.  
    43. void TriggerThread();
    44. void refMe(MyObject* theValue);
    45.  
    46. private:
    47.  
    48. MyThread* myThread;
    49. };
    To copy to clipboard, switch view to plain text mode 

    test.cpp

    Qt Code:
    1. #include "test.h"
    2. #include <QDebug>
    3.  
    4. void MyThread::refMyObject(MyObject* theValue)
    5. {
    6. MyObjectPtr = theValue;
    7. QObject::connect(MyObjectPtr, SIGNAL(TriggerThread()), this, SLOT(MyThreadsSlot()));
    8. }
    9.  
    10. void MyThread::MyThreadsSlot()
    11. {
    12. qDebug() << " Executing Slot in " << this;
    13. }
    14.  
    15. void MyThread::run()
    16. {
    17. exec();
    18. }
    19.  
    20.  
    21. MyObject::MyObject(QObject *parent) : QObject(parent)
    22. {
    23. qDebug() << " Main thread is " << this;
    24. myThread = new MyThread();
    25. QObject::connect(this, SIGNAL(refMe(MyObject *)), myThread, SLOT(refMyObject(MyObject*)));
    26. myThread->start();
    27.  
    28. emit refMe(this);
    29.  
    30. emit TriggerThread();
    31. emit TriggerThread();
    32. emit TriggerThread();
    33. }
    To copy to clipboard, switch view to plain text mode 

    main.cpp
    Qt Code:
    1. #include <QtCore/QCoreApplication>
    2. #include "test.h"
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QCoreApplication a(argc, argv);
    7.  
    8. MyObject thisIsATest;
    9.  
    10. return a.exec();
    11. }
    To copy to clipboard, switch view to plain text mode 

  3. #3
    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: Executing slots in a separate QThread?

    Quote Originally Posted by kachofool View Post
    I have a quick question regarding the start up of a new thread, separate to the main thread, and executing a slot in it, from a signal invoked from the main GUI thread. I understand this behaviour is not normally recommended.
    It's fine.

    I just wanted to know if using moveToThread is the right way to do this (what if the thread quits or is terminated?)
    Moving the thread controller to the thread it controls is ok. If the thread quits, the object will probably go back under control of the thread that spawned the child thread in the first place (although that's just my assumption). If you want to do it another way then there is a very easy way to do it. In run() create an object of a new class that will contain the slot you want executed (instead of placing the slot where you have it now - in the thread class).

    Here is an example:
    Qt Code:
    1. class SolutionBringer : public QObject {
    2. Q_OBJECT
    3. public:
    4. //...
    5. public slots:
    6. void MyThreadSlot() { ... }
    7. };
    8.  
    9. class Thread : public QThread {
    10. Q_OBJECT
    11. public:
    12. // ...
    13. void run() {
    14. SolutionBringer bringer;
    15. connect(this, SIGNAL(TriggerThread()), &bringer, SLOT(MyThreadSlot()));
    16. emit ready();
    17. exec();
    18. }
    19. signals:
    20. void TriggerThread();
    21. void ready();
    22. };
    23.  
    24. // ...
    25.  
    26. Thread *thread = new Thread(...);
    27. connect(obj, SIGNAL(TriggerThread()), thread, SIGNAL(TriggerThread()));
    28. connect(thread, SIGNAL(ready()), &loop, SLOT(quit()));
    29. thread->start();
    30. loop.exec(); // wait until the thread signals it started its work
    31. // ...
    To copy to clipboard, switch view to plain text mode 
    Your biological and technological distinctiveness will be added to our own. Resistance is futile.

    Please ask Qt related questions on the forum and not using private messages or visitor messages.


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

    Chuk (21st February 2010)

  5. #4
    Join Date
    Oct 2009
    Posts
    33
    Thanks
    2

    Default Re: Executing slots in a separate QThread?

    Thanks to both for the replies! Sorry to bump this thread up again, I just wanted to confirm -- when any QObject receives signals, the exec() event loop of the thread it lives in dispatches those signals right?

    That's why you can either have one object be both your actual object and thread object (in this case the object is your thread controller and has whatever custom functionality was required to create the object in the first place as well), *or* you can have two objects, one to solely define your thread, and one for the custom object. In both cases, the object needs to live inside the thread to have its signals dispatched by the thread's exec() loop. Is this correct?

Similar Threads

  1. Replies: 8
    Last Post: 27th March 2013, 11:51
  2. Why slots in QThread subclasses are unsafe?
    By AlphaWolf in forum Qt Programming
    Replies: 8
    Last Post: 30th May 2010, 15:39
  3. QTableWidget, QThread, signals and slots
    By kazek3018 in forum Newbie
    Replies: 4
    Last Post: 30th December 2008, 21:21
  4. QThread - multi threaded signals and slots
    By rishid in forum Qt Programming
    Replies: 4
    Last Post: 30th March 2008, 01:47

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.