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. [Solved] QObject back to main thread
QtWS25 Last Chance

[Solved] QObject back to main thread

Scheduled Pinned Locked Moved General and Desktop
11 Posts 4 Posters 34.2k Views
  • 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.
  • M Offline
    M Offline
    Maxbester
    wrote on last edited by
    #1

    Hi there,

    I wonder how to get back an object running in a QThread to the main thread?

    The following code runs in the main thread:

    @QThread *thread = new QThread();

    MyObject *object = new MyObject();

    object->moveToThread(thread);

    thread->start();@

    I would like to get back the object instance to the main thread. I've tried (from the main thread):

    @object->moveToThread(QApplication::instance()->thread());@

    But I've got: @QObject::moveToThread: Current thread (0x00000001) is not the object's thread (0x00000002). Cannot move to target thread (0x00000002)@

    I've also tried to do it from the object itself:

    @moveToThread(QApplication::instance()->thread());@

    Same error...

    Any idea?

    1 Reply Last reply
    0
    • B Offline
      B Offline
      b1gsnak3
      wrote on last edited by
      #2

      Please read the "warning":http://qt-project.org/doc/qt-4.8/qobject.html#moveToThread posted in the moveToThread documentation. You must move the object from the thread you created. You cannot pull it back into your thread from your main thread. Also your 2 tries are actually just one try as your moveToThread is called in your mainThread not in your worker thread.

      1 Reply Last reply
      0
      • M Offline
        M Offline
        Maxbester
        wrote on last edited by
        #3

        [quote author="b1gsnak3" date="1366208403"]Please read the "warning":http://qt-project.org/doc/qt-4.8/qobject.html#moveToThread posted in the moveToThread documentation. You must move the object from the thread you created. You cannot pull it back into your thread from your main thread. Also your 2 tries are actually just one try as your moveToThread is called in your mainThread not in your worker thread.[/quote]

        Yes I read this but how to do?

        I am obliged to subclass QThread then, aren't I?

        1 Reply Last reply
        0
        • JKSHJ Offline
          JKSHJ Offline
          JKSH
          Moderators
          wrote on last edited by
          #4

          [quote author="Maxbester" date="1366206856"]I've also tried to do it from the object itself:

          @moveToThread(QApplication::instance()->thread());@

          Same error...[/quote]Hi,

          This piece of code will work, IF it is called from the other thread.

          Keep in mind, when you move a QObject to another thread, the only guarantee you get is this: The QObject's slots will run in the other thread, if invoked through a queued connection.

          Example:
          @
          class MyObject : public QObject
          {
          public slots:
          void doWork();
          }

          //--------
          void OtherObject::foo()
          {
          this->obj = new MyObject();
          this->thread = new QThread(this);

          obj->moveToThread(thread);
          connect(this, SIGNAL(startWork()), obj, SLOT(doWork()));
          thread->start();
          
          
          // ======================================
          // Two ways of calling MyObject::doWork()
          // ======================================
          obj->doWork(); // Direct function call; runs doWork() in the main thread. BAD.
          
          emit startWork(); // Queued invokation; runs doWork() in the other thread
          

          }
          @

          So, you can make the object move itself, by putting moveToThread() in a slot and invoking that slot.

          But before that, it might be more useful to ask: Why do you need to move the object back to the main thread?

          Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

          1 Reply Last reply
          1
          • M Offline
            M Offline
            Maxbester
            wrote on last edited by
            #5

            Okay thanks for your reply. It makes sense.

            For my knowledge, is it possible to call a slot with:
            @QMetaObject::invokeMethod(obj,"doWork", Qt::QueuedConnection)@

            ?

            Actually, I want to move back the object to the main thread when the user closes a modal window. The thread has been launched by this modal window and I don't want to lose the object when closing it. So I reimplemented the event function to send a stop signal to the object. When the object receives it, it does the moveToThread(QApplication::instance()->thread).

            The problem is when I send the stop() signal in a queue connection, it is received 52 seconds after the user asked to close the window...

            Can you think of a work around?

            Thanks

            1 Reply Last reply
            0
            • JKSHJ Offline
              JKSHJ Offline
              JKSH
              Moderators
              wrote on last edited by
              #6

              [quote author="Maxbester" date="1366273841"]Okay thanks for your reply. It makes sense.

              For my knowledge, is it possible to call a slot with:
              @QMetaObject::invokeMethod(obj,"doWork", Qt::QueuedConnection)@

              ?

              [/quote]You're welcome :) Yes you're right, QMetaObject::invokeMethod() will cause the slot to run in the other thread too.

              [quote]
              Actually, I want to move back the object to the main thread when the user closes a modal window. The thread has been launched by this modal window and I don't want to lose the object when closing it. So I reimplemented the event function to send a stop signal to the object. When the object receives it, it does the moveToThread(QApplication::instance()->thread).

              The problem is when I send the stop() signal in a queue connection, it is received 52 seconds after the user asked to close the window...

              Can you think of a work around?

              Thanks[/quote]52 seconds is a very long time. It sounds like something is blocking the thread's event loop. Does your object run a long for/while loop? Is there a function that takes a long time to return? (If a function doesn't return, then signals that are queued in the event loop can't be processed -- they will wait until the function returns).

              May I ask what kind of processing do you do in the thread that's launched by the modal window?

              Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

              1 Reply Last reply
              0
              • M Offline
                M Offline
                Maxbester
                wrote on last edited by
                #7

                Yes this is a very long time. I am trying to find if a function doesn't return but for now I cannot find any. I don't have any loop. I hope I don't need any to use threads... Do I?

                My application is a bit complex. The modal window aims to inform the user about the initialization state of a hardware device.

                The thread contains the functions that control the hardware (COM protocol). Some of them are blocking indeed. They wait for a QWaitCondition but they also have a time out less than 30 seconds (so it doesn't explain the 52 seconds).

                Periodically, the hardware sends events. To catch them, I declared another thread in the hardware controller. This other thread only listens the device's events.
                This way, even if the hardware controller thread is blocked, the events are caught. The listener wakes up the QWaitCondition depending on the event it receives (or the wait condition is released if the time out is reached).

                Maybe I should make sure all wait conditions are released when trying to stop the thread?

                1 Reply Last reply
                0
                • JKSHJ Offline
                  JKSHJ Offline
                  JKSH
                  Moderators
                  wrote on last edited by
                  #8

                  No, you don't need to create a for/while loop to use threads. In fact, creating one is a common mistake that blocks thread functions, which is why I brought it up; it's good that you don't have blocking loops.

                  However, if your thread is waiting for a QWaitCondition, the end result is the same as a blocking loop -- execution will stall until the wait condition is fulfilled or the wait times out. That means: until the wait condition is released, the function that initiated the wait will not return. If the function doesn't return, control doesn't return to the thread's event loop. If control doesn't return to the event loop, queued slots can't start executing.

                  I'm guessing that you have a 52 second delay because 2 or more "wait sessions" happen sequentially, before your function returns and the event loop gets its chance to process the "stop" signal.

                  Without seeing your code it's hard to recommend the optimal solution, but here's a general suggestion that works in many cases: Replace low-level synchronization primitives (mutexes, wait conditions, etc.) with Qt's high-level events. Your listener can emit signals instead of waking up QWaitConditions -- split your hardware initialization across different slots, and use your listener's signals to choose which slot to invoke. This way, your thread is never blocked, and your "stop" signal will be processed immediately.

                  See "this page":http://qt-project.org/wiki/Threads_Events_QObjects#2b40afeff6025af55f25a6c7ea5ab3bc for examples (pay particular attention to the "Networking / state machines" and "Jobs splittable in chunks" sections)

                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                  1 Reply Last reply
                  0
                  • M Offline
                    M Offline
                    Maxbester
                    wrote on last edited by
                    #9

                    Thank you for the very good reply.

                    At first, I did what you recommand. That is to say two slots for each initialization step. But I found this code not very "pretty". So I moved to wait conditions.

                    Finally I found how to do. The hardware thread will be started by the main QMainWindow when program is launched. Then it will pass a reference of the hardware object to other sub-windows. Actually I don't think the thread has to be stopped until the applications closes. I will query the hardware all along the execution.

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

                      (REMOVED POST) - Sorry I replied to a posted in the wrong tab of my web browser. LOL.

                      1 Reply Last reply
                      0
                      • A Offline
                        A Offline
                        achmed
                        wrote on last edited by
                        #11
                        This post is deleted!
                        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