Page 1 of 2 12 LastLast
Results 1 to 20 of 39

Thread: Using QTimer in a QThread

  1. #1
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Using QTimer in a QThread

    I don't get it. I want to start a thread that periodically executes a function using a timer.

    Qt Code:
    1. Thread::Thread(QObject *parent) : QThread(parent)
    2. {
    3. start();
    4. }
    5.  
    6. void Thread::run()
    7. {
    8. QTimer t;
    9. connect(&t, SIGNAL(timeout()), this, SLOT(tick()));
    10. t.start(100);
    11. //t.moveToThread(this);
    12. exec();
    13. }
    14.  
    15. void Thread::tick()
    16. {
    17. qDebug() << currentThreadId() << "tick()";
    18. }
    19.  
    20.  
    21.  
    22. class ThreadTest : public QWidget
    23. {
    24.  
    25. Thread thread;
    26.  
    27. ...
    28. };
    29.  
    30. ThreadTest::ThreadTest(QWidget *parent)
    31. : QWidget(parent)
    32. {
    33. qDebug() << QThread::currentThreadId() << "is the main thread.";
    34. }
    To copy to clipboard, switch view to plain text mode 

    And the output I get is:
    Qt Code:
    1. 0x12b8 is the main thread.
    2. 0x12b8 tick()
    3. 0x12b8 tick()
    4. 0x12b8 tick()
    5. 0x12b8 tick()
    6. ...
    To copy to clipboard, switch view to plain text mode 

    Obviously, the timer is still running on the main thread. Using the moveToThread() doesn't make a difference. What's not right about this?

    Changing the timer to an infinite loop with sleep() works though.

    Qt Code:
    1. void Thread::run()
    2. {
    3. forever
    4. {
    5. tick();
    6. sleep(1);
    7. }
    8. }
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. 0xa04 is the main thread.
    2. 0xfa0 tick()
    3. 0xfa0 tick()
    4. 0xfa0 tick()
    5. ...
    To copy to clipboard, switch view to plain text mode 

  2. #2
    Join Date
    Nov 2010
    Posts
    315
    Thanked 53 Times in 51 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Using QTimer in a QThread

    Problem is that you are doing that wrong!
    Qt Code:
    1. class TestClass : QObject
    2. {
    3. Q_OBJECT
    4. public:
    5. TestClass(QObject *parent=0);
    6.  
    7. public slots:
    8. void tick();
    9. };
    10.  
    11. TestClass::TestClass(QObject *parent) : QObject(parent)
    12. {
    13. QTimer *t = new QTimer(this);
    14. connect(t, SIGNAL(timeout()), this, SLOT(tick()));
    15. }
    16.  
    17. void TestClass::tick()
    18. {
    19. qDebug() << currentThreadId() << "tick()";
    20. }
    21.  
    22. // and somewhere
    23. QThread *thread = new QThread(something);
    24. TestClass *object = new TestClass(); // can't pass parent!!!!!!
    25. object->moveToThread(thread);
    26. thread->start();
    27.  
    28. ....
    29. delete object;
    30. thread->WaitFor();
    31. // delete thread;
    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: Using QTimer in a QThread

    Problem is that you are doing that wrong!
    I don't see what he is doing wrong, in respect to the link you posted, except for what he tried in the second bit, which is wrong because you need to be in the "other thread" to call moveToThread().
    The link you provided is talking about using moveToThread() wrong usage, and that you should not always use a subclass of QThread for your threads.
    But there are many cases where this is the RIGHT way to go.
    Even if from an OOP design point of view this is wrong, from implementation point of view this still should work (the original code with out moveToThread()).
    And if it doesn't we need to understand why.

    His code is almost the same as the example code QThread docs, just that he uses a QTimer and not a QTcpSocket.
    Since the QTimer is allocated in run() its should have the thread affinity of the new thread, and from what the OP shows, it looks like its affinity is to the main GUI thread, which is surprising.

    My guess is that it has to do with calling start() in the thread constructor.
    Try removing the start() form the constructor, and call it normally from outside, see if this changes things.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  4. #4
    Join Date
    Nov 2010
    Posts
    315
    Thanked 53 Times in 51 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Using QTimer in a QThread

    Read carefully QObject::connect especially about last 5ht argument (Qt::ConnectionType-enum)!


    Added after 5 minutes:


    Note that your QThread belongs to main thread so default connection here is redirected through posting an event.
    Read article I gave you at beginning to avoid other mistakes.
    Last edited by MarekR22; 12th April 2011 at 11:43.

  5. #5
    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: Using QTimer in a QThread

    Read carefully QObject::connect especially about last 5ht argument (Qt::ConnectionType-enum)!
    Right as if you read carfully you will discover that the default is Qt::AutoConnection, which is:
    Qt::AutoConnection 0 (default) If the signal is emitted from a different thread than the receiving object, the signal is queued, behaving as Qt::QueuedConnection. Otherwise, the slot is invoked directly, behaving as Qt:irectConnection. The type of connection is determined when the signal is emitted.
    EDIT:
    However, now I see why the thread affinity is "wrong".
    Its not - since the QThread object it self is in the main GUI thread, you are getting the main thread id.
    The timer is correctly in the new thread, but the signal is evoking a slot in the main thread!

    Note that your QThread belongs to main thread so default connection here is redirected through posting an event.
    So, it has nothing to do with the fact the an object created in the QThread::run() should have the new thread affinity!

    Read article I gave you at beginning to avoid other mistakes.
    I have read it more than once, and I know it not from yesterday.
    The article is good, but has nothing to do with the question in the first post! - unless you can show otherwise.

    Conclution:
    @OP: your code is behaving correctly.
    Your timer IS in the new thread, but your slot is in the main thread.
    Last edited by high_flyer; 12th April 2011 at 11:55.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

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

    Cruz (12th April 2011)

  7. #6
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Using QTimer in a QThread

    Quote Originally Posted by high_flyer View Post
    @OP: your code is behaving correctly.
    Your timer IS in the new thread, but your slot is in the main thread.
    Thanks, this is a very reasonable explanation. A simple thread.moveToThread(&thread) in the constructor of the gui did the trick and now the slot is executed in the worker thread.

  8. #7
    Join Date
    Nov 2010
    Posts
    315
    Thanked 53 Times in 51 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Using QTimer in a QThread

    NOOOOO!
    Read article I gave you! NEVER EVER move thread to itself! You are corrupting handling of signals and slots from QThread which should be used to manipulate thread.
    Look on my code!

  9. #8
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Using QTimer in a QThread

    Ah sorry, I didn't study your instructions thoroughly enough. So if I understand right, moving the thread to itself means that the inherited signals and slots from QThread will also be handled in that event loop instead of in the main thread. So what? How does that corrupt things?

  10. #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: Using QTimer in a QThread

    A simple thread.moveToThread(&thread) in the constructor of the gui did the trick and now the slot is executed in the worker thread.
    Well, then comes the question of design.
    Even though moving the the thread object to the thread the QThread object created is permited, its a clear sign of a design flaw.
    Maybe if you explain what you are trying to do the correct way can be offered.

    I want to start a thread that periodically executes a function using a timer.
    If you need some functionality done in some time interval, then you better do things the other way around.
    Have a timer in the main thread, and in the timeout slot create a new thread that does the work do be done.
    You might want to have a look at QtConcurrent for a very simple way of doing that.
    http://doc.qt.nokia.com/latest/qtconcurrent.html
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  11. #10
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Using QTimer in a QThread

    OK here is what I want to do. I have a GUI application that controls a robot via serial communication. The only requirement is simple. The communication loop with the robot should execute with a steady pace (every 10 ms), no matter how busy the gui keeps the CPU. The gui shows an interactive OpenGL 3D model of the robot, so when the user is rotating the model wildly and frequent redraws occur, the gui can get very cpu hungry.

  12. #11
    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: Using QTimer in a QThread

    In that case there are several options:
    1. using your original construct you can use QtConcurrent::run() in the timer slot to run a method in which you handle the serial communication to the robot.
    This will ensure that both your timer and the serial communication are not done in the GUI thread.
    2. Put the serial communication functionality in a QObject, allocate that object also in the run() where your timer is allocated, and connect the timer timeout to a slot of your serial communication object.
    3. handle the serial communication in run(), in a while loop, and sleep for 10ms every iteration, then you don't need signals slots and timers.
    This you also can implement using QtConcurrent.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  13. #12
    Join Date
    Jan 2009
    Location
    Germany
    Posts
    387
    Thanks
    101
    Thanked 15 Times in 15 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows

    Default Re: Using QTimer in a QThread

    When I implemented option 3. I found that sleeping in a loop gives me a much more steady timing than using a QTimer. Actually, I measure the runtime of each iteration using Windows' high performance counter and adjust the amount of time to sleep accordingly. This gives very satisfying results. Also, Sleep() seems to be a bit more accurate than msleep().

    In option 1. I would use a thread to run the QTimer and then invoke another thread (or take one from a thread pool) each time I call QtConcurrent::run()? It sounds to me like it has one too many complications.

    Option 2. can be used as a complementary technique along with either option 1 or 3. The only reason I would do that is to circumvent the "you are not doing it right" hack that was linked above. Personally, I find it very natural and intuitive to subclass QThread and do all thready things right there. And if it requires a moveToThread() call that is frowned upon, then so be it. Only if it really does mess something up I'm willing to introduce yet another object, but my question from my earlier post is still unanswered.

    Also I'm hoping that using a QThread and giving it a high priority might improve the serialcom steadiness when the GUI is going nuts, but I haven't stress tested this assumption yet.

    So, what's the advantage of using QtConcurrent::run() instead of a QThread::run()? Since QtConcurrent apparently takes threads from a pool, I assume it's faster if you start a lot of small threads all the time. But does it really matter for one thread that runs through in an infinite loop as in option 3.? The remark in the documentation saying "Note that the function may not run immediately; the function will only be run when a thread is available." is discouraging.

  14. #13
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    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: Using QTimer in a QThread

    How steady is "steady"? If you are not running a real-time operating system then you can't get exact timings no matter how hard you try. Threading will not help you here in any way.
    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.


  15. #14
    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: Using QTimer in a QThread

    Only if it really does mess something up I'm willing to introduce yet another object,
    If objects are designed correctly, such that each object encapsulates a specific functionality, they are correct to be used, even if they are many.
    Otherwise, you get pieces of code sharing implementation of several functionalities, causing dependencies which is a bad thing.

    Any way, I offered the three options, since I don't know your full requirements.
    Each of them has advantages and disadvantages, dependent on your needs.
    Pick the one you think best suits your needs.


    So, what's the advantage of using QtConcurrent::run() instead of a QThread::run()?
    The advantage is encapsulation, which is a very good thing when programming with OOP language.
    And a slim code.

    . Threading will not help you here in any way.
    @wysota:
    Threading helps him to avoid the GUI thread, which according to him, can get very busy, thus influencing the serial communication he needs.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  16. #15
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    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: Using QTimer in a QThread

    Quote Originally Posted by high_flyer View Post
    @wysota:
    Threading helps him to avoid the GUI thread, which according to him, can get very busy, thus influencing the serial communication he needs.
    This is virtual safety. Threads are scheduled by the operating system. If it decides not to schedule the communication thread in a particular point in time, it won't. If the communication thread has little to do compared to the other thread, it will get less time from the operating system increasing a chance to lose the "steadiness" required. Only real-time operating systems give guarantees about times and scheduling.
    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.


  17. #16
    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: Using QTimer in a QThread

    only real-time operating systems give guarantees about times and scheduling.
    True.
    But if you put things in another thread you have more control over what is going on.
    You can also prioritize the threads for example.
    Of course you can't expect real time behavior in a non real time system (well, that too is a question of granularity requirements), but if you know the limits in which you are working, the accuracy of the system maybe acceptable.
    At any rate, by putting the two pars in separate threads you are decoupling them, which I think was one of the main gaols here.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  18. #17
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,360
    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: Using QTimer in a QThread

    Quote Originally Posted by high_flyer View Post
    But if you put things in another thread you have more control over what is going on.
    Again, that's "virtual" control.

    You can also prioritize the threads for example.
    Not really and not always.

    Of course you can't expect real time behavior in a non real time system (well, that too is a question of granularity requirements), but if you know the limits in which you are working, the accuracy of the system maybe acceptable.
    That's gambling. At any point another process may pop in and be given priority over yours so that your process is scheduled not often enough to reach the required communication frequency and you have totally no influence on that.

    At any rate, by putting the two pars in separate threads you are decoupling them, which I think was one of the main gaols here.
    Sure. Only that it's completely pointless.
    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.


  19. #18
    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: Using QTimer in a QThread

    Common witek, so what are you saying?
    You should not implement tasks that need time resolutions in ms range in non RTOS?
    I am sure you, just as I have, made many such usages of threads that are "real time like" under windows/linux.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

  20. #19
    Join Date
    Nov 2010
    Posts
    315
    Thanked 53 Times in 51 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows Symbian S60 Maemo/MeeGo

    Default Re: Using QTimer in a QThread

    Quote Originally Posted by Cruz View Post
    Ah sorry, I didn't study your instructions thoroughly enough. So if I understand right, moving the thread to itself means that the inherited signals and slots from QThread will also be handled in that event loop instead of in the main thread. So what? How does that corrupt things?
    Simple example:
    lets say user starts thread by pressing button, so you connect buttons click signal with start slot of thread. Every think should work since is done by the book.
    But it will not work since you made a queued connection (objects are in two diffident threads since you've moved thread to itself and auto-detection of queued connection was done) and signal to start thread is waiting in event loop of thread which is not started so you have dead lock.

  21. #20
    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: Using QTimer in a QThread

    @MarekR22:
    You example is wrong.
    If QThread object didn't call start(), its run() is not running, thus the read does not exist, and QThread object's affinity in to the thread in which is was created.
    You can't moveToThread() that does not exist.
    ==========================signature=============== ==================
    S.O.L.I.D principles (use them!):
    https://en.wikipedia.org/wiki/SOLID_...iented_design)

    Do you write clean code? - if you are TDD'ing then maybe, if not, your not writing clean code.

Similar Threads

  1. QTimer within QThread
    By Eos Pengwern in forum Qt Programming
    Replies: 6
    Last Post: 23rd February 2011, 20:00
  2. qthread / qtimer
    By Galen in forum Qt Programming
    Replies: 5
    Last Post: 17th April 2010, 22:57
  3. QThread and QTimer
    By sivrisinek in forum Qt Programming
    Replies: 4
    Last Post: 30th April 2009, 16:41
  4. QThread & QTimer
    By hosseinyounesi in forum Qt Programming
    Replies: 5
    Last Post: 13th April 2009, 08:22
  5. QTimer and QThread
    By TheKedge in forum Qt Programming
    Replies: 4
    Last Post: 21st September 2006, 14:52

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.