Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Making asynchronous calls work like synchronous calls
Forum Updated to NodeBB v4.3 + New Features

Making asynchronous calls work like synchronous calls

Scheduled Pinned Locked Moved General and Desktop
11 Posts 5 Posters 14.9k Views 2 Watching
  • 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.
  • J Offline
    J Offline
    JulienMaille
    wrote on last edited by
    #1

    Dear Qt users,
    I know this topic has been discussed all over the web. The usual suggestion is to use this: @QEventLoop loop;
    loop.connect(object, SIGNAL(operationCompleted()), SLOT(quit()));
    object->startOperation();
    loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);@ However I was wondering: what happens if the signal is emitted before we call loop.exec()?
    Could we stay stuck in the exec()? Particularly if the startOperation() calls processEvents?

    I have used this trick a few times in the past, but I'm now struggling with an asynchronous activex.
    I can confirm that the operationCompleted() signal is emitted. However the loop never quits.
    I've noticed that startOperation() takes a little time (500msec) and I don't know what happens there.

    1 Reply Last reply
    0
    • A Offline
      A Offline
      Adrien Leravat
      wrote on last edited by
      #2

      Hi Julien M,

      You could definitively stay stuck in the exec() if the "operationCompleted" signal is triggered. That is because signals are processed synchroneously in a single thread application, or if you call processEvent like you said.

      To avoid this issue, you can you a QTimer::singleShot(0, object, SLOT ( startOperation() ) to trigger the start immediately after exec is called (after preceding events of course). Using "0" as duration posts an event that is processed the next event loop iteration.

      Adeneo Embedded - www.adeneo-embedded.com

      1 Reply Last reply
      0
      • J Offline
        J Offline
        JulienMaille
        wrote on last edited by
        #3

        Bonsoir Adrien.
        Could you please detail the real reason for getting stuck in exec()?
        As long as object->startOperation() does not handle an event loop, the emitted signal should be queued and processed by the exec() even if it emitted to early, right?

        Regarding your solution, again, could you detail it? Do you suggest this: @QEventLoop loop;
        loop.connect(object, SIGNAL(operationCompleted()), SLOT(quit()));
        loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
        QTimer::singleShot(0, object, SLOT(startOperation());@ Cause it sounds like the singleShot will never be reached!

        1 Reply Last reply
        0
        • A Offline
          A Offline
          Adrien Leravat
          wrote on last edited by
          #4

          If your startOperation method contains an "emit operationCompleted()", then it will immediately trigger the quit slot of your event loop. When you write "emit signal()", in a single threaded application, all slots connected are called immediately, not posted.

          To change this behaviour, you can use the fourth argument of the connect method: "connect (&sender, sig, &receiver, slot, Qt::QueuedConnection) ":http://doc.qt.digia.com/qt/qobject.html#connect

          So in your case, it could look like...
          @
          myfunction::startProcessing
          -> object::startOperation -> emit operationCompleted() -> QEventLoop::quit() // Does nothing
          -> QEventLoop::exec() // Will never quit
          @

          The same issue arises if you call processEvents() in you operationCompleted, even with an asynchronous connection.

          The single shot timer should be used just before the exec(). That way, the event is posted, and the startOperation slot will be executed "from inside" the event loop.
          @
          QEventLoop loop;
          loop.connect(object, SIGNAL(operationCompleted()), SLOT(quit()));
          QTimer::singleShot(0, object, SLOT(startOperation());
          loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
          @

          Bonne soirée :)

          Adeneo Embedded - www.adeneo-embedded.com

          1 Reply Last reply
          1
          • U Offline
            U Offline
            utcenter
            wrote on last edited by
            #5

            What about Qt::QueuedConnection and Qt::BlockingQueuedConnection?

            1 Reply Last reply
            0
            • J Offline
              J Offline
              JulienMaille
              wrote on last edited by
              #6

              Ok, then is it right to say that the original piece of code from my first post is another example of "You are doing it wrong"?
              If yes, why can we find this example here (last line of the table)
              http://www.developer.nokia.com/Community/Wiki/TSQ001335_-_Asynchronous_operations_in_S60_and_Qt

              1 Reply Last reply
              0
              • K Offline
                K Offline
                KA51O
                wrote on last edited by
                #7

                If you have a look at "this article":http://www.developer.nokia.com/Community/Wiki/How_to_wait_synchronously_for_a_Signal_in_Qt you will see that they do not recommend the approach for real applications. There are a number of problem that can arise if you are not 100% sure of what you are doing (race condition, recursive event loops,...).

                Also I would recommend to always use a Timer for having the eventloop time out after a certain time.
                @
                QEventLoop loop;
                QTimer timer;
                timer.setInterval(YOUR_TIMEOUT_IN_MILLISECS);
                timer.setSingleShot(true);
                connect(&timer, SIGNAL(timeout()), &loop, SLOT(quit()));
                connect(object, SIGNAL(operationCompleted()), &loop, SLOT(quit()));
                QTimer::singleShot(0, object, SLOT(startOperation()));
                loop.exec(QEventLoop::AllEvents|QEventLoop::WaitForMoreEvents);
                @

                1 Reply Last reply
                0
                • J Offline
                  J Offline
                  JulienMaille
                  wrote on last edited by
                  #8

                  Would be nice to be able to determine if the QEventLoop has been stopped by the signal or by the timeout.

                  1 Reply Last reply
                  0
                  • K Offline
                    K Offline
                    KA51O
                    wrote on last edited by
                    #9

                    just connect the timeout to another slot which then notifies you about the timeout.

                    1 Reply Last reply
                    0
                    • A Offline
                      A Offline
                      andre
                      wrote on last edited by
                      #10

                      You might also be interested in the so-called "Delta Object Rules":http://delta.affinix.com/dor/ These rules, especially the second one, specifically describes the issue you run into where a finished() signal is send immediately after a request().

                      I find it a good read.

                      If you want to wait for one or more signals, you could also take a look at libQxt. There is a "QxtSignalWaiter":http://libqxt.bitbucket.org/doc/0.6/qxtsignalwaiter.html class that does all you need.

                      1 Reply Last reply
                      0
                      • J Offline
                        J Offline
                        JulienMaille
                        wrote on last edited by
                        #11

                        Andre ... you rock!

                        1 Reply Last reply
                        0

                        • Login

                        • Login or register to search.
                        • First post
                          Last post
                        0
                        • Categories
                        • Recent
                        • Tags
                        • Popular
                        • Users
                        • Groups
                        • Search
                        • Get Qt Extensions
                        • Unsolved