Qt Forum

    • Login
    • Search
    • Categories
    • Recent
    • Tags
    • Popular
    • Users
    • Groups
    • Search
    • Unsolved

    Update: Forum Guidelines & Code of Conduct

    Signal/slot across threads - remove duplicate events in event loop

    General and Desktop
    6
    9
    12716
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • S
      ShawnG last edited by

      Hello,

      I have several signal/slot connections between a worker thread and the GUI thread. Using the default delivery method, which posts an event in the GUI's event queue, one of my connections can occasionally emit signals faster into the event queue than the slot being called. So what happens is multiple signals are being queue that are just repeats and the queue gets backed up. Is there a method to ensure that only one signal (event) is in the queue at a time?

      Thanks!

      1 Reply Last reply Reply Quote 0
      • A
        andre last edited by

        As far as I know, there is no such method.
        I think it would be best the throttle the number of messages you are sending at the source. The best performance of multi-threaded applications can be reached if you communicate as little as possible between threads. They should be as independent as possible. Do you really need to send updates to the GUI thread that fast?

        In the past, I have throttled the delivery of update messages from a worker to the GUI thread to at most two per second, and that worked very well for me.

        1 Reply Last reply Reply Quote 0
        • B
          broadpeak last edited by

          Read this topics in help, maybe:

          QCoreApplication::hasPendingEvents ()
          QCoreApplication::removePostedEvents ( QObject * receiver, int eventType )

          1 Reply Last reply Reply Quote 0
          • S
            ShawnG last edited by

            I did look at the QCoreApplication::removePostedEvents ( QObject * receiver, int eventType ) method, but I am not sure what the eventType would be for a signal/slot.

            1 Reply Last reply Reply Quote 0
            • S
              ShawnG last edited by

              After looking through the source, the eventType is: MetaCall (value 43 in 4.6.3)

              1 Reply Last reply Reply Quote 0
              • B
                baysmith last edited by

                To use QCoreApplication::removePostedEvents(), you could create a custom event. Then the event type would be known.

                You may also consider communicating through an atomic flag. The receiver could then poll when it is able to handle information from the worker thread.

                Of course neither of these methods are as convenient as signals/slots.

                Nokia Certified Qt Specialist.

                1 Reply Last reply Reply Quote 0
                • F
                  fluca1978 last edited by

                  I think that if you have to deliver so much events as so fast rates you have to build your own event queue, that will notify (via signals) your GUI thread once at a time and the GUI thread will process (consume) all of the events in the queue. So the queue will work as a concentrator for the incoming events: the sender thread will post events, the queue will store and present them in a block to the GUI thread when this is signalled.

                  1 Reply Last reply Reply Quote 0
                  • A
                    andre last edited by

                    Perhaps you can use the technique I described "here":http://developer.qt.nokia.com/wiki/Delay_action_to_wait_for_user_interaction to limit the number of signals going down the event queue. Interesting to see that it actually is possible to manipulate the contents of the eventqueue.

                    1 Reply Last reply Reply Quote 0
                    • S
                      ScumCoder last edited by ScumCoder

                      Allow me to revive this topic, since more than a decade later it is still as relevant as ever.

                      @andre said in Signal/slot across threads - remove duplicate events in event loop:

                      In the past, I have throttled the delivery of update messages from a worker to the GUI thread to at most two per second, and that worked very well for me.

                      This isn't a proper solution, because it relies on a wild guess about the time needed for the consumer to consume. One day you'll have your code run on a machine on which the GUI thread takes more than 0.5 s to process a request, and boom, unbounded queue growth.

                      If the receiver is the GUI thread (and thus the events that you send there are just to refresh the GUI), the proper way is to have the GUI thread reply to the worker thread with ACKs.
                      In the worker class:

                      1. Have a boolean variable called "SignalRequested" or something like that. It doesn't even have to be atomic.
                      2. Have a slot that will assert this boolean, called "RequestSignal" or something like that.
                      3. Inside the producer loop, check this boolean, and if it's true, reset it back to false and emit the signal.

                      In the GUI class:

                      1. Invoke the RequestSignal slot on the worker during startup.
                      2. Wherever you receive the signal from the worker, refresh the UI and start a single-shot timer connected to the RequestSignal slot on the worker. The timer's interval will determine the GUI's refresh rate.

                      There you go, an effective solution that'll guarantee at most a single undelivered signal at all times.

                      If the receiver is not the GUI thread, the only proper way is to make your own queue (at least until Qt provides us with means to control its internal one).

                      1. Write a RingBuffer class (check Wikipedia for examples).
                      2. Instantiate it with the type of your event.
                      3. Protect this instance with a mutex.
                      4. Add a WaitCondition.
                      5. Implement the classic producer/consumer pattern.
                        Voila: now, in the Producer thread, you can actually assess the situation whenever you are going to add an event to the queue and do some meaningful things if the queue grows too much - issue a warning, drop the event, etc., instead of blindly shoving events into the queue and hoping for the best.
                      1 Reply Last reply Reply Quote 0
                      • First post
                        Last post