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. GUI operations across threads (again)
Forum Updated to NodeBB v4.3 + New Features

GUI operations across threads (again)

Scheduled Pinned Locked Moved Solved General and Desktop
31 Posts 5 Posters 9.4k 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.
  • H Offline
    H Offline
    Harry123
    wrote on last edited by
    #1

    The subject of GUI operations across threads is heavily discussed, but while studying it I have found two conflicting basic answers :

    1. GUI operations across threads are impossible - use signals and slots
    2. GUI operations across threads are possible - enclose GUI operations in the thread within qApp->lock() and qApp->unlock()

    I am faced with porting to Qt a large Windows product which has only one GUI thread and multiple worker threads. Using the first method would require creating hundreds of signals and slots, so I would prefer to avoid it. My problem is that the second method is only mentioned in relatively older documentation of Qt.

    Should using the second method be possible, I could limit the locking to small fragments of code that manipulate GUI object attributes or do show/hide, and for GUI objects created in a thread use moveToThread to move them to the GUI thread.

    So my question is : Does the qApp->lock() method still exist, or only signals and slots ? If it exists, can it be used as described above ?

    kshegunovK C 2 Replies Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi
      I was wondering. what does the current large Windows product do now?

      use events?

      Normally gui operations is never permitted from
      other thread so I wonder how it works now?

      ps. I could not find lock() in Qt5

      H 1 Reply Last reply
      2
      • mrjjM mrjj

        Hi
        I was wondering. what does the current large Windows product do now?

        use events?

        Normally gui operations is never permitted from
        other thread so I wonder how it works now?

        ps. I could not find lock() in Qt5

        H Offline
        H Offline
        Harry123
        wrote on last edited by Harry123
        #3

        @mrjj

        Under Windows, GUI operations work across threads - it's just good practice to use a mutex, which is why the port this way would be much easier since everything is already in place.

        And it seems like lock() is now gone in Qt5, which explains the lack of newer documentation. Is there any other way of blocking the GUI event loop from the thread for a short while ?

        1 Reply Last reply
        0
        • H Harry123

          The subject of GUI operations across threads is heavily discussed, but while studying it I have found two conflicting basic answers :

          1. GUI operations across threads are impossible - use signals and slots
          2. GUI operations across threads are possible - enclose GUI operations in the thread within qApp->lock() and qApp->unlock()

          I am faced with porting to Qt a large Windows product which has only one GUI thread and multiple worker threads. Using the first method would require creating hundreds of signals and slots, so I would prefer to avoid it. My problem is that the second method is only mentioned in relatively older documentation of Qt.

          Should using the second method be possible, I could limit the locking to small fragments of code that manipulate GUI object attributes or do show/hide, and for GUI objects created in a thread use moveToThread to move them to the GUI thread.

          So my question is : Does the qApp->lock() method still exist, or only signals and slots ? If it exists, can it be used as described above ?

          kshegunovK Offline
          kshegunovK Offline
          kshegunov
          Moderators
          wrote on last edited by
          #4

          @Harry123

          So my question is : Does the qApp->lock() method still exist, or only signals and slots ? If it exists, can it be used as described above ?

          http://doc.qt.io/qt-5/qapplication-members.html
          It appears it doesn't, and I personally don't remember such a method at all. In what version of Qt you saw that method?

          Under Windows, GUI operations work across threads

          I really, really doubt that. Can you provide a reference for this claim?

          it's just good practice to use a mutex

          Nope. It's simply necessary when you need a mutual exclusion lock. In a single thread a mutex is simply unnecessary overhead.

          Is there any other way of blocking the GUI event loop from the thread for a short while ?

          Possibly. It depends. When you want to block it, and from which thread?

          Read and abide by the Qt Code of Conduct

          H 1 Reply Last reply
          1
          • kshegunovK kshegunov

            @Harry123

            So my question is : Does the qApp->lock() method still exist, or only signals and slots ? If it exists, can it be used as described above ?

            http://doc.qt.io/qt-5/qapplication-members.html
            It appears it doesn't, and I personally don't remember such a method at all. In what version of Qt you saw that method?

            Under Windows, GUI operations work across threads

            I really, really doubt that. Can you provide a reference for this claim?

            it's just good practice to use a mutex

            Nope. It's simply necessary when you need a mutual exclusion lock. In a single thread a mutex is simply unnecessary overhead.

            Is there any other way of blocking the GUI event loop from the thread for a short while ?

            Possibly. It depends. When you want to block it, and from which thread?

            H Offline
            H Offline
            Harry123
            wrote on last edited by Harry123
            #5

            @kshegunov

            lock() was apparently last seen in QT3.

            Windows GUI operations do work across threads and we do a lot of them - within reason of course. This is pragmatic, as much of the documentation of the older parts of the SDK still dates from Windows 3.1 and doesn't include the better multi-threading introduced with the NT kernel. Object handles in Windows NT are a global resource, not limited to one thread.

            From your strong objection I take it that it wouldn't work with Qt (or was never tested) ? Would you have any idea of a technique that can minimize the number of signals/slots ?

            kshegunovK 1 Reply Last reply
            0
            • H Harry123

              @kshegunov

              lock() was apparently last seen in QT3.

              Windows GUI operations do work across threads and we do a lot of them - within reason of course. This is pragmatic, as much of the documentation of the older parts of the SDK still dates from Windows 3.1 and doesn't include the better multi-threading introduced with the NT kernel. Object handles in Windows NT are a global resource, not limited to one thread.

              From your strong objection I take it that it wouldn't work with Qt (or was never tested) ? Would you have any idea of a technique that can minimize the number of signals/slots ?

              kshegunovK Offline
              kshegunovK Offline
              kshegunov
              Moderators
              wrote on last edited by kshegunov
              #6

              @Harry123 said:

              lock() was apparently last seen in QT3.

              This explains it. Qt 3 is really, really ancient.

              Windows GUI operations do work across threads and we do a lot of them

              Okay, I'll assume you're correct, although MSDN mentions nothing of this.

              From your strong objection I take it that it wouldn't work with Qt (or was never tested) ?

              Objection to? I was just asking when and from where you want to block the event loop. If you're talking about Qt, it doesn't matter if the win API is thread-safe, the Qt GUI is not, and it's not even reentrant.

              Would you have any idea of a technique that can minimize the number of signals/slots ?

              Direct function calls. But why would you want to minimize them in the first place? I'd think you should want to maximize them ...

              Read and abide by the Qt Code of Conduct

              1 Reply Last reply
              0
              • mrjjM Offline
                mrjjM Offline
                mrjj
                Lifetime Qt Champion
                wrote on last edited by
                #7

                @Harry123
                Hi
                I was wondering the windows app u are porting. Is it qt3 ? or a native win app?

                Must you must re-create the GUI in Qt and the threads or can you reuse those?

                H 1 Reply Last reply
                0
                • H Harry123

                  The subject of GUI operations across threads is heavily discussed, but while studying it I have found two conflicting basic answers :

                  1. GUI operations across threads are impossible - use signals and slots
                  2. GUI operations across threads are possible - enclose GUI operations in the thread within qApp->lock() and qApp->unlock()

                  I am faced with porting to Qt a large Windows product which has only one GUI thread and multiple worker threads. Using the first method would require creating hundreds of signals and slots, so I would prefer to avoid it. My problem is that the second method is only mentioned in relatively older documentation of Qt.

                  Should using the second method be possible, I could limit the locking to small fragments of code that manipulate GUI object attributes or do show/hide, and for GUI objects created in a thread use moveToThread to move them to the GUI thread.

                  So my question is : Does the qApp->lock() method still exist, or only signals and slots ? If it exists, can it be used as described above ?

                  C Offline
                  C Offline
                  cheezus
                  wrote on last edited by cheezus
                  #8

                  @Harry123 Can't you just use QMetaObject::invokeMethod? This will do the right thing.

                  1 Reply Last reply
                  1
                  • mrjjM mrjj

                    @Harry123
                    Hi
                    I was wondering the windows app u are porting. Is it qt3 ? or a native win app?

                    Must you must re-create the GUI in Qt and the threads or can you reuse those?

                    H Offline
                    H Offline
                    Harry123
                    wrote on last edited by Harry123
                    #9

                    @mrjj : It's a native win app.

                    @cheezus : Does QMetaObject::invokeMethod require calling connect, or can it just call any slot? Not requiring connect will reduce the amount of coding.

                    kshegunovK C 2 Replies Last reply
                    0
                    • H Harry123

                      @mrjj : It's a native win app.

                      @cheezus : Does QMetaObject::invokeMethod require calling connect, or can it just call any slot? Not requiring connect will reduce the amount of coding.

                      kshegunovK Offline
                      kshegunovK Offline
                      kshegunov
                      Moderators
                      wrote on last edited by
                      #10

                      @Harry123 said:

                      Does QMetaObject::invokeMethod require calling connect, or can it just call any slot?

                      You can call any slot and/or invokable function (i.e. one that has been declared with the Q_INVOKABLE macro).

                      Read and abide by the Qt Code of Conduct

                      H 1 Reply Last reply
                      1
                      • kshegunovK kshegunov

                        @Harry123 said:

                        Does QMetaObject::invokeMethod require calling connect, or can it just call any slot?

                        You can call any slot and/or invokable function (i.e. one that has been declared with the Q_INVOKABLE macro).

                        H Offline
                        H Offline
                        Harry123
                        wrote on last edited by
                        #11

                        @kshegunov :
                        @cheezus :

                        That's nice to know.
                        I assume that QMetaObject::invokeMethod is the best solution, and will try it in a limited way over the next few days.

                        kshegunovK 1 Reply Last reply
                        0
                        • H Harry123

                          @mrjj : It's a native win app.

                          @cheezus : Does QMetaObject::invokeMethod require calling connect, or can it just call any slot? Not requiring connect will reduce the amount of coding.

                          C Offline
                          C Offline
                          cheezus
                          wrote on last edited by
                          #12

                          @Harry123 No, it can call any function exposed to the meta object system.

                          1 Reply Last reply
                          0
                          • H Harry123

                            @kshegunov :
                            @cheezus :

                            That's nice to know.
                            I assume that QMetaObject::invokeMethod is the best solution, and will try it in a limited way over the next few days.

                            kshegunovK Offline
                            kshegunovK Offline
                            kshegunov
                            Moderators
                            wrote on last edited by kshegunov
                            #13

                            @Harry123
                            QMetaObject::invokeMethod has somewhat limited uses, and I really doubt this will solve your problem.
                            As I told @mrjj over the chat you have much bigger problems than the threading. Qt's widgets are alien (non-native) and the painting is done over a single window's surface (device context handle). Each of the child widgets manages its own geometry and does its painting, but only the top-level widget actually holds a handle to the window surface. When there's a paint event the top-level window will delegate the painting to the child widgets who actually paint on the top-level windows's surface. This I don't see how you're going to be able to work around easily. Possibly by enforcing native widgets all along the object tree, but this'd cause a bit hit on performance.

                            Read and abide by the Qt Code of Conduct

                            C 1 Reply Last reply
                            0
                            • kshegunovK kshegunov

                              @Harry123
                              QMetaObject::invokeMethod has somewhat limited uses, and I really doubt this will solve your problem.
                              As I told @mrjj over the chat you have much bigger problems than the threading. Qt's widgets are alien (non-native) and the painting is done over a single window's surface (device context handle). Each of the child widgets manages its own geometry and does its painting, but only the top-level widget actually holds a handle to the window surface. When there's a paint event the top-level window will delegate the painting to the child widgets who actually paint on the top-level windows's surface. This I don't see how you're going to be able to work around easily. Possibly by enforcing native widgets all along the object tree, but this'd cause a bit hit on performance.

                              C Offline
                              C Offline
                              cheezus
                              wrote on last edited by
                              #14

                              @kshegunov I don't see how that's relevant but I missed the chat so perhaps there is some missing context.

                              kshegunovK 1 Reply Last reply
                              0
                              • C cheezus

                                @kshegunov I don't see how that's relevant but I missed the chat so perhaps there is some missing context.

                                kshegunovK Offline
                                kshegunovK Offline
                                kshegunov
                                Moderators
                                wrote on last edited by
                                #15

                                @cheezus said:

                                I don't see how that's relevant but I missed the chat so perhaps there is some missing context.

                                Nope, you didn't miss much. The relevance is this:
                                The OP is asking how he can paint using the win API from multiple threads onto widgets. So there are two problems, one how to thread the GUI code (which as established would be iffy at best), and secondly how to paint with the win API over widgets. I think the second problem is much more hard to work around.

                                Read and abide by the Qt Code of Conduct

                                C 1 Reply Last reply
                                0
                                • kshegunovK kshegunov

                                  @cheezus said:

                                  I don't see how that's relevant but I missed the chat so perhaps there is some missing context.

                                  Nope, you didn't miss much. The relevance is this:
                                  The OP is asking how he can paint using the win API from multiple threads onto widgets. So there are two problems, one how to thread the GUI code (which as established would be iffy at best), and secondly how to paint with the win API over widgets. I think the second problem is much more hard to work around.

                                  C Offline
                                  C Offline
                                  cheezus
                                  wrote on last edited by
                                  #16

                                  @kshegunov I take OP to mean "I have an existing WINAPI project that draws on multiple windows from multiple threads and I need to port this to Qt"

                                  The real response to this thread is what does this code look like? If it is simply setting labels or adding stuff to lists. Then yes, invokeMethod will work fine. If he is literally using GDI calls to paint onto a surface, then that requires a different approach. There are multiple options here but the real answer depends on what this magic WINAPI application looks like. It also depends on the target platforms.

                                  OP, hire someone who knows what they're doing to guide you otherwise you'll just be creating future bugs/crashes if you guess your way through it.

                                  kshegunovK 1 Reply Last reply
                                  1
                                  • C cheezus

                                    @kshegunov I take OP to mean "I have an existing WINAPI project that draws on multiple windows from multiple threads and I need to port this to Qt"

                                    The real response to this thread is what does this code look like? If it is simply setting labels or adding stuff to lists. Then yes, invokeMethod will work fine. If he is literally using GDI calls to paint onto a surface, then that requires a different approach. There are multiple options here but the real answer depends on what this magic WINAPI application looks like. It also depends on the target platforms.

                                    OP, hire someone who knows what they're doing to guide you otherwise you'll just be creating future bugs/crashes if you guess your way through it.

                                    kshegunovK Offline
                                    kshegunovK Offline
                                    kshegunov
                                    Moderators
                                    wrote on last edited by
                                    #17

                                    @cheezus

                                    If he is literally using GDI calls to paint onto a surface, then that requires a different approach

                                    This is how I understand it.

                                    Read and abide by the Qt Code of Conduct

                                    C H 2 Replies Last reply
                                    0
                                    • kshegunovK kshegunov

                                      @cheezus

                                      If he is literally using GDI calls to paint onto a surface, then that requires a different approach

                                      This is how I understand it.

                                      C Offline
                                      C Offline
                                      cheezus
                                      wrote on last edited by
                                      #18

                                      @kshegunov Then heaven help us all

                                      1 Reply Last reply
                                      0
                                      • kshegunovK kshegunov

                                        @cheezus

                                        If he is literally using GDI calls to paint onto a surface, then that requires a different approach

                                        This is how I understand it.

                                        H Offline
                                        H Offline
                                        Harry123
                                        wrote on last edited by Harry123
                                        #19

                                        @kshegunov :
                                        @cheezus :

                                        NO! Absolutely NOT! No drawing from multiple threads. This one-million line application was (somewhat) ported to Qt, but for the moment the multi-thread part is #define'd out, which disables many functions.

                                        About multi-thread support in Windows :

                                        Some Windows objects, like timers, need to be created in their thread, but can then be killed from any other, in spite of what the outdated documentation says.

                                        But don't forget that practically all Windows objects have a message interface via SendMessage and PostMessage. Even when the SDK offers seemingly direct functions, internally many are implemented as sent messages. This includes practically all objects : push-buttons, checkboxes, comboboxes, tree objects etc. Which allows Windows to be completely thread-agnostic for very many types of operations. Windows since NT is a real multi-threaded OS whose SDK is (almost) completely re-entrant and thread-safe. The "main" thread has no further significance than that of the system library automatically installing there an event loop.

                                        By comparison, Qt uses direct function calls which almost always precludes inter-thread operations. While being much more esthetic and powerful than Windows SDK, it also requires some acrobatics when programming multiple threads.

                                        It would be nice if some future version of Qt could also become thread-agnostic for these types of operations, automatically crossing thread boundaries with invokeMethod or other. This will in effect supersede much of the current mechanical need for signals/slots, leaving them for more sophisticated needs.

                                        For a dummy example : If a thread wants to call QPushButton::setText, a signal and a slot are required, and maybe also sub-classing QPushButton, which I see as much too much bother for such a trivial thing.

                                        kshegunovK C 2 Replies Last reply
                                        1
                                        • H Harry123

                                          @kshegunov :
                                          @cheezus :

                                          NO! Absolutely NOT! No drawing from multiple threads. This one-million line application was (somewhat) ported to Qt, but for the moment the multi-thread part is #define'd out, which disables many functions.

                                          About multi-thread support in Windows :

                                          Some Windows objects, like timers, need to be created in their thread, but can then be killed from any other, in spite of what the outdated documentation says.

                                          But don't forget that practically all Windows objects have a message interface via SendMessage and PostMessage. Even when the SDK offers seemingly direct functions, internally many are implemented as sent messages. This includes practically all objects : push-buttons, checkboxes, comboboxes, tree objects etc. Which allows Windows to be completely thread-agnostic for very many types of operations. Windows since NT is a real multi-threaded OS whose SDK is (almost) completely re-entrant and thread-safe. The "main" thread has no further significance than that of the system library automatically installing there an event loop.

                                          By comparison, Qt uses direct function calls which almost always precludes inter-thread operations. While being much more esthetic and powerful than Windows SDK, it also requires some acrobatics when programming multiple threads.

                                          It would be nice if some future version of Qt could also become thread-agnostic for these types of operations, automatically crossing thread boundaries with invokeMethod or other. This will in effect supersede much of the current mechanical need for signals/slots, leaving them for more sophisticated needs.

                                          For a dummy example : If a thread wants to call QPushButton::setText, a signal and a slot are required, and maybe also sub-classing QPushButton, which I see as much too much bother for such a trivial thing.

                                          kshegunovK Offline
                                          kshegunovK Offline
                                          kshegunov
                                          Moderators
                                          wrote on last edited by kshegunov
                                          #20

                                          @Harry123 said:

                                          But don't forget that practically all Windows objects have a message interface via SendMessage and PostMessage.

                                          Qt's objects have that message interface as well. QCoreApplication::sendMessage and QCoreApplicaiton::postMessage.

                                          PS
                                          The win API is C. It has no objects (in the C++ meaning), it has handles (which are opaque pointers to some internal structure). Its message processing is also synchronous, which X11's is not. But I don't want to enter a debate on the win API and its design, or lack thereof.

                                          The "main" thread has no further significance than that of the system library automatically installing there an event loop.

                                          As recently asked, you can in principle create Qt's application object (thus the main event loop) in a thread different from the main one.

                                          By comparison, Qt uses direct function calls

                                          It uses signals to notify of state changes, and slots to respond to those changes. This however does not preclude any threading and/or doesn't require acrobatics, only some understanding of how the framework actually works.

                                          It would be nice if some future version of Qt could also become thread-agnostic for these types of operations, automatically crossing thread boundaries with invokeMethod or other.

                                          QMetaObject::invokeMethod is safe across thread boundaries (with auto/queued/blocking queued connection type), so that's already in place.

                                          This will in effect supersede much of the current mechanical need for signals/slots ... For a dummy example ...

                                          It will most certainly supersede nothing. Your thread is not supposed to know of the existence of push buttons at all. The worker object that sits in that thread is supposed to just notify anyone that's interested something has happened. That's what decoupling means in the first place. The moment your thread or worker object know of the push button you couple them up, and if something changes (e.g. the push button becomes a label) you go about changing/inspecting every place where that object was used.

                                          Read and abide by the Qt Code of Conduct

                                          H 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