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. Qt UI, blocking calls, and reentrancy
Qt 6.11 is out! See what's new in the release blog

Qt UI, blocking calls, and reentrancy

Scheduled Pinned Locked Moved General and Desktop
5 Posts 2 Posters 8.8k Views 1 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.
  • ? Offline
    ? Offline
    A Former User
    wrote on last edited by
    #1

    I come from a Microsoft world, where because of how COM works with STA apartments, blocking calls such as to WaitOne, or to WCF services, do not prevent re-entrancy. This is because blocking calls does not completely block, but allows for certain types of messages to continue being pumped, including paint, input and any posted messages. The COM message pump implementation does initially enter a wait state, but if any new messages meeting the required filter for MsgWaitForMultipleObjects() are received, it awakens. This is by design for a number of reasons, to prevent undesired blocking on a UI thread being among them. The proper way to perform asynchronous actions like WCF web service calls is either to use asynchronous design patterns, which implement callbacks to inform the caller of completion, or else to perform synchronous web service calls on a worker thread, rather than on the UI thread.

    I am wondering if the same concept and recommendation applies to Qt.

    Thanks,

    1 Reply Last reply
    0
    • M Offline
      M Offline
      MuldeR
      wrote on last edited by
      #2

      In Qt applications you will normally call QApplication::exec() from your main thread in your main() function. This will start the event loop. Usually the application won't return from there, until it terminates. The event loop does all the event processing for you and it will keep the GUI responsive. If you need to react to a certain event, then you will use the "Signals and Slots":http://qt-project.org/doc/qt-4.8/signalsandslots.html concept of Qt: You connect a slot to the signal that you want to react to. Every time the signal is emitted, the slot will be called. Much like a "callback", but with type safety.

      If both objects, the sender and receiver, live in the same thread, a "direct" connection will be used by default. This means that the emit will block until the slot has returned. Also the slot will be executed in the context of the thread that has executed the emit. When connecting objects that belong to different threads, then a "queued" connection is used by default. With such connection, the emit returns immediately. The slot will be executed in the context of the thread to which the receiver belongs. Using queued connections requires the thread to which the receiver belongs to execute an event loop, because the event loop will call the slot eventually.

      If a slot that was called from the main thread is blocking for too long, the GUI will become unresponsive! So if you want to do an "asynchronous" call, you need to create a background/worker thread with QThread. Update messages or results can be send from the "background" thread to the "main" thread via Signals & Slots. Using a "queued" connection makes it thread-safe, because the slot will always be executed by the "main" thread's event loop, even when the signal was emitted from the background thread.

      If you want to wait synchronously for some signal, but keep the GUI responsive, you can create your own "local" event loop. Just connect the signal to your event loop's quit() slot:
      http://www.developer.nokia.com/Community/Wiki/How_to_wait_synchronously_for_a_Signal_in_Qt

      Alternatively, you may have a look at "QFuture":http://doc.qt.nokia.com/4.7-snapshot/qtconcurrentrun.html for asynchronous calls!

      Hope that helps ;-)

      My OpenSource software at: http://muldersoft.com/

      Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

      Go visit the coop: http://youtu.be/Jay...

      1 Reply Last reply
      0
      • ? Offline
        ? Offline
        A Former User
        wrote on last edited by
        #3

        Thanks very much,

        If the UI calls a function that absolutely must run to completion before any other UI code is called, so no re-entrancy, what are recommendations to achieve this?

        As I mentioned, there is in Microsoft UI technologies potentially issue with re-entrancy even if call a wait primitive such as WaitOne because of how the COM message pump works -- if this call is done on a UI thread.

        1. UI calls methodA that has networkIO
        2. Since methodA has networkIO, the thread calls a wait primitive of some type, waiting for response
        3. Because of how COM message pump works, if a message is sent to the UI, with SendMessage, the message pump will process the message and call UI function, even though still waiting for a response from the network

        Kurt

        1 Reply Last reply
        0
        • M Offline
          M Offline
          MuldeR
          wrote on last edited by
          #4

          Well, if you call some function from the main thread (which executes the event loop) and that function blocks, then the GUI will simply freeze until the function returns. This, of course, will make sure that no other function can be called from the GUI until the previous function has returned. Simply because the main thread (event loop) is blocked and won't process any events (e.g. user input). But it obviously is not a good idea to call a "blocking" function directly from the GUI, at least if the call takes longer than few milliseconds. Instead you may create a "background" thread with the help of QThread and call the "blocking" function from that thread. The main thread would simply launch the thread and then continue to do event processing in order to keep the GUI responsive. QThread has a finished() signal which you can use to react when the thread has terminated.

          @MainWindow::initOperation(void)
          {
          if(!myThread) //already in progress?
          {
          m_myThread = new MyThread(<parameters here>);
          connect(myThread, SIGNAL(finished()), this, SLOT(operationDone()));
          myThread->start();
          }
          }

          MainWindow::operationDone(void)
          {
          QMessageBox::information(this, tr("Done"), tr("Yeah, it's done!"));
          delete myThread; myThread = NULL;
          }@
          @MyThread::run(void)
          {
          someFunctionThatWillBlockForALongTime();
          }@

          My OpenSource software at: http://muldersoft.com/

          Qt v4.8.6 MSVC 2013, static/shared: http://goo.gl/BXqhrS

          Go visit the coop: http://youtu.be/Jay...

          1 Reply Last reply
          0
          • ? Offline
            ? Offline
            A Former User
            wrote on last edited by
            #5

            Great, thank you.

            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