Results 1 to 15 of 15

Thread: QThread and QEventLoop - Idle Processing

  1. #1
    Join Date
    Aug 2007
    Posts
    14
    Thanks
    6
    Qt products
    Qt4
    Platforms
    Windows

    Default

    After reading the documentation, I'm still not quite clear on how to use a QEventLoop to do idle processing in a QThread. Basically I want to have a thread that connects a device. Once a device is connected I want to use idle processing to poll the device. The user can terminate the thread using the quit function (which disconnects the device if necessary). As far as I understand, this is how you make your thread enter an event loop when it is started.

    Qt Code:
    1. void MyThread::run()
    2. {
    3. exec();
    4. }
    To copy to clipboard, switch view to plain text mode 

    So my question basically is: where do I put the code that does the polling of the device?

    To make your application perform idle processing (i.e. executing a
    special function whenever there are no pending events), use a
    QTimer with 0 timeout. More sophisticated idle processing schemes
    can be achieved using processEvents().
    Can someone post an example for this? What are the " sophisticated idle processing schemes"?

    Here is a rough overview of how my run function would look without an event loop:

    Qt Code:
    1. void MyThread::run()
    2. {
    3. connect_device();
    4.  
    5. done = false;
    6.  
    7. while(!done)
    8. {
    9. poll_device();
    10. }
    11.  
    12. disconnect_device();
    13. }
    14.  
    15. void MyThread::quit()
    16. {
    17. done = true;
    18. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by wysota; 26th February 2008 at 00:57. Reason: Merged two posts

  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: QThread and QEventLoop - Idle Processing

    Quote Originally Posted by kloffy View Post
    Can someone post an example for this?
    You will need an object that will do the polling:
    Qt Code:
    1. class Poller : public QObject
    2. {
    3. Q_OBJECT
    4. public:
    5. Poller();
    6. ~Poller();
    7.  
    8. public slots:
    9. void poll();
    10. void stop();
    11.  
    12. private:
    13. QTimer timer;
    14. };
    15.  
    16. Poller::Poller()
    17. {
    18. // open the device
    19. connect( &timer, SIGNAL( timeout() ), this, SLOT( poll() ) );
    20. timer.start( 100 ); // wait at least 100 ms between polling
    21. }
    To copy to clipboard, switch view to plain text mode 

    Now all you have to do is to create such Poller object in your thread. Note that if this is the only object that lives in that thread, it will be always "idle".

    Quote Originally Posted by kloffy View Post
    What are the " sophisticated idle processing schemes"?
    You can pass some flags to processEvents() to control what events should be processed.

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

    kloffy (25th February 2008)

  4. #3
    Join Date
    Aug 2007
    Posts
    14
    Thanks
    6
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QThread and QEventLoop - Idle Processing

    Thank you! That was exactly what I was looking for. It just so happens that I stumbled upon a similar example right before I saw your post. It had suspend function to stop the timer, which is pretty neat. If anyone's interested:

    Qt Code:
    1. class MyThreadObject : public QObject {
    2. QTimer myTimer;
    3.  
    4. MyThreadObject() {
    5. connect( &myTimer, timeout(), this, onTimeOut());
    6. }
    7.  
    8. slot onSuspendThread() {
    9. myTimer.stop();
    10. }
    11.  
    12. slot onResumeThread() {
    13. myTimer.start(0);
    14. }
    15.  
    16. private slot onTimeOut() {
    17. // do a few comutation steps.
    18. // Should return "quickly" to the event loop
    19. }
    20.  
    21. }
    22.  
    23.  
    24. class MyThread : public QThread {
    25. slot MyThread:run() {
    26. MyThreadObject threadObject; //=> the threadObject affinity is the thread
    27. // here, connect the appropriate signals to the appropriate slots
    28.  
    29. threadObject.onResumeThread();
    30. exec();
    31. }
    32.  
    33. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by kloffy; 25th February 2008 at 22:56.

  5. #4
    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: QThread and QEventLoop - Idle Processing

    I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread. You can as well use this:

    Qt Code:
    1. void Thread::run() {
    2. while(!finished){
    3. poll();
    4. QThread::msleep(100);
    5. }
    6. }
    To copy to clipboard, switch view to plain text mode 

  6. The following 2 users say thank you to wysota for this useful post:

    kloffy (27th February 2008)

  7. #5
    Join Date
    Aug 2007
    Posts
    14
    Thanks
    6
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QThread and QEventLoop - Idle Processing

    Quote Originally Posted by wysota View Post
    I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread.
    Yes, but if I understood correctly then it wouldn't be possible to connect signals/slots with objects in other threads. (Using queued connections)

  8. #6
    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: QThread and QEventLoop - Idle Processing

    It would be possible. You could emit signals but you couldn't have queued slots. If you have a single object that only polls for data, you don't need slots, so...

  9. #7
    Join Date
    Mar 2008
    Location
    Norway
    Posts
    7
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread and QEventLoop - Idle Processing

    Quote Originally Posted by wysota View Post
    I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread. You can as well use this:

    Qt Code:
    1. void Thread::run() {
    2. while(!finished){
    3. poll();
    4. QThread::msleep(100);
    5. }
    6. }
    To copy to clipboard, switch view to plain text mode 
    This was my first approach to a similar problem. But, what would be the best way to stop the thread then?

    Since I want to terminate the thread from "outside", I guess that would be to set the finished variable to true and then call wait(). But then again the finished variable will be accessed from two different threads and need to be protected by a Mutex?

  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: QThread and QEventLoop - Idle Processing

    Quote Originally Posted by Mhondoz View Post
    This was my first approach to a similar problem. But, what would be the best way to stop the thread then?
    Set the "finished" flag to true.

    But then again the finished variable will be accessed from two different threads and need to be protected by a Mutex?
    No, it doesn't, because only one thread may change the flag. The worst that may happen is that the thread will perform once cycle more, which is completely ignorable.

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

    Mhondoz (6th March 2008)

  12. #9
    Join Date
    Mar 2008
    Location
    Norway
    Posts
    7
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread and QEventLoop - Idle Processing

    Ok, thanks. :-)

    So if I understand correctly, this will work and is thread safe:

    mythread.h
    Qt Code:
    1. class MyThread : public QThread {
    2.  
    3. public:
    4. MyThread(QObject *parent);
    5. ~MyThread();
    6.  
    7. protected:
    8. void run();
    9.  
    10. private:
    11. bool _bFinished;
    12.  
    13. };
    To copy to clipboard, switch view to plain text mode 

    mythread.cpp
    Qt Code:
    1. MyThread::MyThread(QObject *parent) :
    2. QThread(parent), _bFinished( false ) {
    3.  
    4. start();
    5. }
    6.  
    7. MyThread::~MyThread() {
    8.  
    9. _bFinished = true;
    10. wait();
    11.  
    12. }
    13.  
    14. void MyThread::run() {
    15.  
    16. while ( ! _bFinished ) {
    17.  
    18. // Do something
    19.  
    20. QThread::msleep( 100 );
    21. }
    22. }
    To copy to clipboard, switch view to plain text mode 

    What I want to accomplish here is to have the thread start when it is constructed, and stop the thread in the destructor. My concern was the _bFinished variable which I believe is accessed by the MyThread thread in the while loop in run(), but in the destructor it will be accessed by the thread that constructed MyThread, for example the main thread...

  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: QThread and QEventLoop - Idle Processing

    It doesn't matter as nothing tries to set _bFinished to false when it's true. And that's the only case when a newly set value could be overwritten with a different value. If you are not sure about it, use QAtomicInt (available since 4.4, so the link is invalid at the time of writing this post).

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

    Mhondoz (6th March 2008)

  15. #11
    Join Date
    Mar 2008
    Location
    Norway
    Posts
    7
    Thanks
    4
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: QThread and QEventLoop - Idle Processing

    That makes sense. Thank you very much. :-)

  16. #12
    Join Date
    Sep 2010
    Posts
    7
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QThread and QEventLoop - Idle Processing

    I all,

    Quote Originally Posted by wysota View Post
    I would just like to notice that if this is the only object living in your thread, there is no point in having the event loop in the thread. You can as well use this:

    Qt Code:
    1. void Thread::run() {
    2. while(!finished){
    3. poll();
    4. QThread::msleep(100);
    5. }
    6. }
    To copy to clipboard, switch view to plain text mode 
    In that case, the polling will happen every 100ms, not doing idle processing. To perform idle processing, a timer with 0 timeout and an event loop are mandatory. Am I correct?

    Thanks
    Last edited by jlemaitre; 28th April 2011 at 10:11. Reason: Question was unclear

  17. #13
    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: QThread and QEventLoop - Idle Processing

    Quote Originally Posted by jlemaitre View Post
    In that case, the polling will happen every 100ms and the event loop is mandatory to perform idle processing. Am I correct?
    Sleep and event loops don't go together well. If you want to do idle processing in the thread besides the main task the thread is doing, use a timer instead of sleep().
    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.


  18. #14
    Join Date
    Sep 2010
    Posts
    7
    Thanks
    2
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: QThread and QEventLoop - Idle Processing

    Quote Originally Posted by wysota View Post
    If you want to do idle processing in the thread besides the main task the thread is doing, use a timer instead of sleep().
    In the initial post of the op, I understood the idle processing is the main task. (Polling the device is the only task of the thread, and it must be done at idle time.) In that case, is its timer-based solution (re-coded below) appropriate?

    Qt Code:
    1. class DevicePoller : public QThread
    2. {
    3. Q_OBJECT
    4. QTimer m_timer;
    5. slots:
    6. void poll();
    7. protected:
    8. virtual void run()
    9. {
    10. connect( m_timer, SIGNAL( timeout() ), this, SLOT( poll() ) );
    11. m_timer.start( 0 );
    12. exec();
    13. }
    14. };
    To copy to clipboard, switch view to plain text mode 

    Or, is it best to avoid timers at all, and launch a thread with QThread::IdlePriority:

    Qt Code:
    1. class DevicePoller : public QThread
    2. {
    3. protected:
    4. virtual void run()
    5. {
    6. while( !finished ) poll();
    7. }
    8. };
    9. DevicePoller mythread;
    10. mythread.start( QThread::IdlePriority );
    11. // ...
    To copy to clipboard, switch view to plain text mode 

    Or, am I wrong and there is another strategy?

    Thanks for the rapid answer anyway!

  19. #15
    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: QThread and QEventLoop - Idle Processing

    Quote Originally Posted by jlemaitre View Post
    In the initial post of the op, I understood the idle processing is the main task. (Polling the device is the only task of the thread, and it must be done at idle time.) In that case, is its timer-based solution (re-coded below) appropriate?
    It's a periodic task, not idle processing.

    Qt Code:
    1. class DevicePoller : public QThread
    2. {
    3. Q_OBJECT
    4. QTimer m_timer;
    5. slots:
    6. void poll();
    7. protected:
    8. virtual void run()
    9. {
    10. connect( m_timer, SIGNAL( timeout() ), this, SLOT( poll() ) );
    11. m_timer.start( 0 );
    12. exec();
    13. }
    14. };
    To copy to clipboard, switch view to plain text mode 
    There is no point in using threads here, you can use the main thread with this approach.

    Or, is it best to avoid timers at all, and launch a thread with QThread::IdlePriority:

    Qt Code:
    1. class DevicePoller : public QThread
    2. {
    3. protected:
    4. virtual void run()
    5. {
    6. while( !finished ) poll();
    7. }
    8. };
    9. DevicePoller mythread;
    10. mythread.start( QThread::IdlePriority );
    11. // ...
    To copy to clipboard, switch view to plain text mode 

    Or, am I wrong and there is another strategy?
    Thread priorities are just hints for the OS, it may ignore them so that's not a good approach -- you'll end up with a busy loop.
    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.


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

    jlemaitre (28th April 2011)

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.