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. Invoking a slot from a non-Qt thread
Forum Updated to NodeBB v4.3 + New Features

Invoking a slot from a non-Qt thread

Scheduled Pinned Locked Moved Unsolved General and Desktop
12 Posts 6 Posters 317 Views 3 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.
  • PerdrixP Offline
    PerdrixP Offline
    Perdrix
    wrote on last edited by
    #1

    I correct to think that there's only two ways to invoke a slot from a non-QObject based thread?

    • Use QMetaObject::invokeMethod(), or

    • emit a signal (can I do that on a non Qt thread?)

    Thanks
    David

    JonBJ 1 Reply Last reply
    0
    • Christian EhrlicherC Offline
      Christian EhrlicherC Offline
      Christian Ehrlicher
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Emit a signal.

      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
      Visit the Qt Academy at https://academy.qt.io/catalog

      1 Reply Last reply
      0
      • PerdrixP Perdrix

        I correct to think that there's only two ways to invoke a slot from a non-QObject based thread?

        • Use QMetaObject::invokeMethod(), or

        • emit a signal (can I do that on a non Qt thread?)

        Thanks
        David

        JonBJ Offline
        JonBJ Offline
        JonB
        wrote on last edited by
        #3

        @Perdrix
        @Christian-Ehrlicher will correct me if I am wrong. Yes, you can emit a signal from a non-QObject based thread. But you still need a "context object" to emit the signal and pass to the connect(). And that needs to be a QObject. And you will use a queued connection. I guess QMetaObject::invokeMethod() will skip the need to have an emitting QObject.

        You will also a need a receiving QObject, for both cases. The Qt event loop needs to be running in the receiver thread to dispatch the slots.

        Am I right, Christian?

        References:
        https://stackoverflow.com/questions/41044526/qt-5-emit-signal-from-non-qt-thread
        https://stackoverflow.com/questions/24982324/qt-emit-a-signal-from-a-c-thread
        https://www.qtcentre.org/threads/65029-Emitting-signal-from-a-non-Qt-Thread

        Christian EhrlicherC 1 Reply Last reply
        0
        • JonBJ JonB

          @Perdrix
          @Christian-Ehrlicher will correct me if I am wrong. Yes, you can emit a signal from a non-QObject based thread. But you still need a "context object" to emit the signal and pass to the connect(). And that needs to be a QObject. And you will use a queued connection. I guess QMetaObject::invokeMethod() will skip the need to have an emitting QObject.

          You will also a need a receiving QObject, for both cases. The Qt event loop needs to be running in the receiver thread to dispatch the slots.

          Am I right, Christian?

          References:
          https://stackoverflow.com/questions/41044526/qt-5-emit-signal-from-non-qt-thread
          https://stackoverflow.com/questions/24982324/qt-emit-a-signal-from-a-c-thread
          https://www.qtcentre.org/threads/65029-Emitting-signal-from-a-non-Qt-Thread

          Christian EhrlicherC Offline
          Christian EhrlicherC Offline
          Christian Ehrlicher
          Lifetime Qt Champion
          wrote on last edited by
          #4

          @JonB said in Invoking a slot from a non-Qt thread:

          Am I right, Christian?

          Yes, but the question was if it can be invoked from a std::thread (or other non QThread based one). Nothing about what object it is 🙂

          Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
          Visit the Qt Academy at https://academy.qt.io/catalog

          JonBJ 1 Reply Last reply
          0
          • Christian EhrlicherC Christian Ehrlicher

            @JonB said in Invoking a slot from a non-Qt thread:

            Am I right, Christian?

            Yes, but the question was if it can be invoked from a std::thread (or other non QThread based one). Nothing about what object it is 🙂

            JonBJ Offline
            JonBJ Offline
            JonB
            wrote on last edited by JonB
            #5

            @Christian-Ehrlicher said in Invoking a slot from a non-Qt thread:

            Yes, but the question was if it can be invoked from a std::thread (or other non QThread based one). Nothing about what object it is 🙂

            Oh indeed! And the reference links are about that, e.g. the second one is about

            I want to emit a signal from a C++ thread (std::thread) in Qt.

            I just meant that OP is going to need to Qt objects around from somewhere in the thread. I agree with you that emit signal is the obvious route. But, just for the record, a non-Qt thread can use QMetaObject::invokeMethod() to call a slot if it has access to a receiving object but not a sending one to do a connect(). Right?

            Christian EhrlicherC 1 Reply Last reply
            0
            • JonBJ JonB

              @Christian-Ehrlicher said in Invoking a slot from a non-Qt thread:

              Yes, but the question was if it can be invoked from a std::thread (or other non QThread based one). Nothing about what object it is 🙂

              Oh indeed! And the reference links are about that, e.g. the second one is about

              I want to emit a signal from a C++ thread (std::thread) in Qt.

              I just meant that OP is going to need to Qt objects around from somewhere in the thread. I agree with you that emit signal is the obvious route. But, just for the record, a non-Qt thread can use QMetaObject::invokeMethod() to call a slot if it has access to a receiving object but not a sending one to do a connect(). Right?

              Christian EhrlicherC Offline
              Christian EhrlicherC Offline
              Christian Ehrlicher
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @JonB said in Invoking a slot from a non-Qt thread:

              a non-Qt thread can use QMetaObject::invokeMethod() to call a slot if it has access to a receiving object but not a sending one to do a connect(). Right?

              Yes. But imo it's better to define a signal in the receiver which then does the thread context switch.

              Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
              Visit the Qt Academy at https://academy.qt.io/catalog

              1 Reply Last reply
              1
              • Axel SpoerlA Offline
                Axel SpoerlA Offline
                Axel Spoerl
                Moderators
                wrote on last edited by
                #7

                In order to emit a signal or use QMetaObject::invokeMethod() from another thread, it doesn't technically have to be a QThread. What's required is an event loop and the emitter / invoker to inherit from QObject. But if you develop an application with Qt, why not use QThread anyway?

                We've seen an implementation in this topic, that circumvents missing QObject inheritance / event loop. It implements methods in a QObject wrapping a QMetaObject::invokeMethod() call on itself. The caller just calls the wrapper from another thread. While it might technically work, I would clearly not recommend it. Instead, make the caller inherit from QObject and let it live in another QThread. All problems solved cleanly.

                Software Engineer
                The Qt Company, Oslo

                JonBJ 1 Reply Last reply
                1
                • Axel SpoerlA Axel Spoerl

                  In order to emit a signal or use QMetaObject::invokeMethod() from another thread, it doesn't technically have to be a QThread. What's required is an event loop and the emitter / invoker to inherit from QObject. But if you develop an application with Qt, why not use QThread anyway?

                  We've seen an implementation in this topic, that circumvents missing QObject inheritance / event loop. It implements methods in a QObject wrapping a QMetaObject::invokeMethod() call on itself. The caller just calls the wrapper from another thread. While it might technically work, I would clearly not recommend it. Instead, make the caller inherit from QObject and let it live in another QThread. All problems solved cleanly.

                  JonBJ Offline
                  JonBJ Offline
                  JonB
                  wrote on last edited by
                  #8

                  @Axel-Spoerl said in Invoking a slot from a non-Qt thread:

                  But if you develop an application with Qt, why not use QThread anyway?

                  I agree. But don't you think Mr @Perdrix is going to say "because it's already in someone else's code which I don't want to change but instead work with"? :)

                  1 Reply Last reply
                  1
                  • PerdrixP Offline
                    PerdrixP Offline
                    Perdrix
                    wrote on last edited by
                    #9

                    The application was not developed using Qt it was developed using MFC. We have converted it to Qt over the last two to three years (it was a pretty large job). Where it was helpful and expedient we did use QThreads, but there are other bits of threading that we've not (yet) got round to...

                    1 Reply Last reply
                    1
                    • Axel SpoerlA Offline
                      Axel SpoerlA Offline
                      Axel Spoerl
                      Moderators
                      wrote on last edited by
                      #10

                      Sounds like squeezing toothpaste back into the tube.
                      I'd probably go for an interface class, living inside the std::thread, inheriting from QObject and running its own QEventLoop.
                      That class can provide wrappers to either invoke methods in other threads, or emit signals.
                      In the moment you could replace the whatever thread with a QThread, you can untangle the interface class and do the calls directly.

                      Software Engineer
                      The Qt Company, Oslo

                      S 1 Reply Last reply
                      0
                      • J.HilkJ Offline
                        J.HilkJ Offline
                        J.Hilk
                        Moderators
                        wrote on last edited by
                        #11

                        I haven't tried anything, but can't you simply pass a qt signal als callback function? Any connects won't auto default to QtQueuedConnection as there's no thread info due to no QThread but you can manage that manually


                        Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


                        Q: What's that?
                        A: It's blue light.
                        Q: What does it do?
                        A: It turns blue.

                        1 Reply Last reply
                        0
                        • Axel SpoerlA Axel Spoerl

                          Sounds like squeezing toothpaste back into the tube.
                          I'd probably go for an interface class, living inside the std::thread, inheriting from QObject and running its own QEventLoop.
                          That class can provide wrappers to either invoke methods in other threads, or emit signals.
                          In the moment you could replace the whatever thread with a QThread, you can untangle the interface class and do the calls directly.

                          S Offline
                          S Offline
                          SimonSchroeder
                          wrote on last edited by
                          #12

                          @Axel-Spoerl said in Invoking a slot from a non-Qt thread:

                          I'd probably go for an interface class, living inside the std::thread, inheriting from QObject and running its own QEventLoop.

                          From what I understand only the calling thread does not have anything Qt-based. In order to emit a signals there is no need to start an event loop inside that non-Qt thread. Only a receiving slot would require an event loop. Or am I wrong about this?

                          The quickest way would certainly be using invokeMethod. However, if you can (and are willing to) using signals is always better. If you don't want to introduce any Qt into that thread (yet) you can have a regular C++ function inside some existing Qt code and call that. This function can either use invokeMethod or even emit a signal for your.

                          If it is inevitable to keep Qt out of your thread (in the long run) it makes sense to create something derived from QObject to be used inside your non-Qt thread. Then you can emit a signal using this object. I don't think you need anything special in the calling thread. emit is just a Qt keyword that gets removed by the preprocessor. From the compiler's point of view emitting a signal is just calling a regular member function. (The member function for the signal is generated by moc.) You need to be careful about object lifetimes. The calling object needs to live long enough for the slot to be executed. If the calling or receiving object in a connect statement is deleted, all queued slot invocations are also removed. Also, as your non-Qt thread does not have an event loop you cannot use deleteLater() to delete the object. If you cannot guarantee that your non-Qt thread runs long enough for the slot to be executed (or rather at least started) inside the Qt thread (and thus cannot guarantee a long lifetime for the QObject-derived object) using invokeMethod is the safest way. Maybe it even makes the most sense to use invokeMethod if you don't rely on member variables of the calling object, but instead hand over all data necessary for the slot as function arguments. It certainly avoid thinking about object lifetimes (and thread lifetimes).

                          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