Search code examples
c++multithreadingqtqt-signalsqtcore

What happens with Qt signals when the receiver is busy?


In my application, I have an instance of QTimer, whose timeout() signal is connected to a slot in the main window object, causing it to get called periodically. The slot takes a picture with a camera and saves it to disk.

I was wondering what happens if the signal is emitted (from a separate thread where QTimer executes, I presume) when the receiver (the window object on the main thread) is currently busy (like with taking and saving the previous picture). Does the call get queued and executed after the previous call terminates? The whole idea is to have it run at regular intervals, but can those calls queue up and then get called randomly when control returns to the event loop, causing a mess? How can I avoid it? Theoretically the slot should execute quickly, but let's say the hardware had some problem and there was a stall.

I would like for calls to be dropped rather than queued in such a situation, and even more useful would be the ability to react when it happens (warn user, terminate execution).


Solution

  • The other answers at this moment have relevant context. But the key thing to know is that if the timer callback is signaling a slot in a different thread, then that connection is either a QueuedConnection or a BlockingQueuedConnection.

    So, if you're using the timer to try and get some sort of regular processing done, then this gives you some additional jitter in timing between when the timer fires and when the slot actually executes, as the receiving object is in it's own thread running an independent event loop. That means it could be doing any number of other tasks when the event is put in the queue and until it finishes processing those events, the picture thread won't execute your timer event.

    The timer should be in the same thread as the photo logic. Putting the timer in the same thread as the camera shot, makes the connection direct, and gives you better stability on your timing intervals. Especially if the photo capture & save has occasional exceptional durations.

    It goes something like this, supposing the interval is 10 seconds:

    • set timer for 10 seconds
    • timer fires
    • save a start time
    • take photo
    • save photo to disk (say it takes 3 seconds for some odd reason)
    • calculate 10-(current time - start time)= seven seconds
    • set time out for seven seconds

    You can also setup some logic here to detect skipped intervals (say one of the operations takes 11 seconds to complete...