[Moved] Connecting signal and slot of different affinity

  • I am trying to run a timer in a different thread. I am connecting the timer's timeout() signal to my scene's advance() slot.

    Here is the code how it is connected:
    TimerThread tThread;
    QObject::connect(&(tThread.timer), SIGNAL(timeout()), &scene, SLOT(advance()));

    And here is the TimerThread's run():
    @void TimerThread::run()
    qDebug() << "Satrting timer...";

    The connection does not seem to work (advance() is never called). The message "Satrting timer..." is printed out when I run the application.

    It works if I create the timer and do the connection in the main thread like this:
    QTimer timer;
    QObject::connect(&timer, SIGNAL(timeout()), &scene, SLOT(advance()));
    qDebug() << "Satrting timer...";
    timer.start(TimerFreq); @

    Any ideas why not working in the different thread?

    PS: Please move the thread to "Desktop", I realized it is wrong section only after posting... Sorry!

  • Because your thread is ending quietly fast :) try to add exec() as the last string of your run() method.

  • Added exec();
    [I modified also the code in the original post]
    Still not working...

  • Do not use threads.

    Since search of the site doesn’t seem to work(infinite time at ”Loading...” phase, it seems...), I can’t give in site resources, but Qt offers so many alternatives for most of threading stuff, so just don’t do it.

    This piece of code tells that you have a TimerThread that is a thread AND has timer inside?! So basically, when you start the thread, what for you start the timer too?

    Then again, I don’t see the code, question is quite impossible to answer properly, sorry for nagging.

  • My main thread is painting something moving in the graphics scene. In order to look smooth to the eye, the movement is supposed to be triggered 30 times / sec. For that I use a timer which on timeout() should trigger advance() which calculates the next position. Advance() will then trigger update() which will repaint the scene.

    When I use the timer in the same main thread, it gets delayed when the event loop queue is very loaded (for example moving continuously my finger on the touch panel and processing the touch events), and the timeout is triggered much later than every 30ms (at 45ms or even 50ms).

    So now I want to move the timer to another thread to get its own event loop and ensure that it will be triggered at the correct intervals.

  • Don't, it's completely and utterly useless.


    Very long story: read my article http://developer.qt.nokia.com/wiki/ThreadsEventsQObjects .

    Short story: first of all, your timer, being a member variable, was built with the wrong thread affinity (the one of the thread that created the tThread object, and not the thread represented by that object). Since the timer is obviously event driven, you're not allowed to start it from run(), that is, from a different thread than the one the timer object is living in.

    Even if you move the timer to the right thread (with moveToThread), it won't work as expected: a queued connection will be used, that is, an event will be posted in the "scene"'s thread's event loop; the handling of this event will invoke the slot. So, wow, now the slot invokations will be posted every 1/30th of second! What's wrong with this? Well, the fact that that event loop is already congested by other touch events, therefore the slot won't be actually invoked every 1/30th of second!

    And no, you can't force a direct connection here, because obviously QGraphicsScene is a GUI object, therefore it's allowed to live only in a one, specific thread (the GUI thread); moreover, it's not threadsafe nor reentrant, so you can call its methods only from the thread it is living in (again, the GUI thread).

Log in to reply