Results 1 to 3 of 3

Thread: QThread event handling and QWaitCondition

  1. #1
    Join Date
    Apr 2009
    Location
    Italy
    Posts
    70
    Thanks
    23
    Thanked 15 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default QThread event handling and QWaitCondition

    Hello,
    I have a main thread (GUI) and a worker thread. From the main thread I'm calling a function in the worker thread that waits for a event to be posted on the worker thread's own queue. But it looks like the event is processed only after the main thread gets control back.

    Here is a complete test class (test.h) that reproduces the problem. As soon as it is created, the worker thread starts a 5 seconds timer. When you click the button in the main widget, it waits for the timer event to be triggered.

    Qt Code:
    1. #include <QThread>
    2. #include <QTimer>
    3. #include <QWaitCondition>
    4. #include <QMutex>
    5. #include <QPushButton>
    6. #include <QVBoxLayout>
    7. #include <QMessageBox>
    8.  
    9. //
    10. // Worker
    11. //
    12. class Worker: public QThread
    13. {
    14. Q_OBJECT
    15. public:
    16. Worker(): tmrNotifyWhenDone(this)
    17. {
    18. // start 5 seconds timer
    19. tmrNotifyWhenDone.setInterval(5000);
    20. connect(&tmrNotifyWhenDone, SIGNAL(timeout()), this, SLOT(onWorkCompleted()));
    21. tmrNotifyWhenDone.start();
    22.  
    23. // enter thread event loop
    24. start();
    25. }
    26.  
    27. bool waitForWorkCompleted() // called from the main thread, see below
    28. {
    29. mutex.lock();
    30. bool ok = workCompleted.wait(&mutex, 6000);
    31. mutex.unlock();
    32.  
    33. return ok;
    34. }
    35.  
    36. private slots:
    37. void onWorkCompleted()
    38. // this is called only when the message box is shown... WHY?
    39. {
    40. workCompleted.wakeAll();
    41. }
    42.  
    43. private:
    44. QTimer tmrNotifyWhenDone;
    45. QMutex mutex;
    46. QWaitCondition workCompleted;
    47. };
    48.  
    49.  
    50. //
    51. // MainWidget
    52. //
    53. class MainWidget : public QWidget
    54. {
    55. Q_OBJECT
    56. public:
    57. MainWidget(QWidget* parent = 0): QWidget(parent)
    58. {
    59. QPushButton* btnWaitWorkCompleted = new QPushButton("Wait for work completed");
    60. connect(btnWaitWorkCompleted, SIGNAL(clicked()), this, SLOT(onBtnWaitWorkCompleted()));
    61.  
    62. QVBoxLayout* layout = new QVBoxLayout();
    63. layout->addWidget(btnWaitWorkCompleted);
    64. setLayout(layout);
    65. }
    66.  
    67. private slots:
    68. void onBtnWaitWorkCompleted()
    69. {
    70. if (worker.waitForWorkCompleted())
    71. QMessageBox::information(0, "Test", "Ok!");
    72. else
    73. QMessageBox::information(0, "Test", "Wrong!");
    74. }
    75.  
    76. private:
    77. Worker worker;
    78. };
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Jul 2009
    Posts
    139
    Thanks
    13
    Thanked 59 Times in 52 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: QThread event handling and QWaitCondition

    You're having the same problem as this post. Only the run function runs in the new thread. The worker object belongs to the thread it was created in, that is the GUI thread. Slots are executed in the thread that their object belongs to.

    You can do either of two things. The first is to move ownership of the worker object to the newly created thread with a call to moveToThread(this). The other is to create your object in the run method so it belongs to the new thread as shown in the other post.

  3. The following user says thank you to numbat for this useful post:

    mattc (21st August 2009)

  4. #3
    Join Date
    Apr 2009
    Location
    Italy
    Posts
    70
    Thanks
    23
    Thanked 15 Times in 11 Posts
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QThread event handling and QWaitCondition

    Quote Originally Posted by numbat View Post
    You're having the same problem as this post.
    Sorry, I didn't notice that post.

    Only the run function runs in the new thread. The worker object belongs to the thread it was created in, that is the GUI thread. Slots are executed in the thread that their object belongs to.
    Ok, now I understand.

    You can do either of two things. The first is to move ownership of the worker object to the newly created thread with a call to moveToThread(this). The other is to create your object in the run method so it belongs to the new thread as shown in the other post.
    Thank you very much, I am going to experiment with your solutions.

Tags for this Thread

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
  •  
Qt is a trademark of The Qt Company.