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. QMetaObject::invokeMethod crash
Forum Updated to NodeBB v4.3 + New Features

QMetaObject::invokeMethod crash

Scheduled Pinned Locked Moved General and Desktop
16 Posts 6 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.
  • T Offline
    T Offline
    Tom C
    wrote on last edited by
    #1

    Hi !

    I'm trying to call a QWidget slot from a worker thread with QMetaObject::invokeMethod but the application crash on invokeMethod.

    @
    void functionRunningOnAWorkerThread()
    {
    QString arg = "Hello World";
    QWidget* w = 0;

    //I call a factory to create a QLabel object from the GUI thread (Blocking call)
    w = viewFactory()->createView("label");

    //At this point w is on the screen and I would like to set its content. So I call "invokeMethod"
    QMetaObject::invokeMethod(w,"setText", Qt::QueuedConnection,Q_ARG(QString,arg)); // CRASH
    }
    @

    I have done similar things before but only with non QWidget objects. I don't know if it is possible to do it with QWidget objects.

    1 Reply Last reply
    0
    • sierdzioS Offline
      sierdzioS Offline
      sierdzio
      Moderators
      wrote on last edited by
      #2

      QWidgets can only be handled by the GUI thread. Send a signal to your main thread with the text you want to set and handle widget manipulation there.

      Try with Qt::BlockingQueuedConnection, too :)

      (Z(:^

      1 Reply Last reply
      0
      • raven-worxR Offline
        raven-worxR Offline
        raven-worx
        Moderators
        wrote on last edited by
        #3

        Edit: nvm :)

        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
        If you have a question please use the forum so others can benefit from the solution in the future

        1 Reply Last reply
        0
        • T Offline
          T Offline
          Tom C
          wrote on last edited by
          #4

          That's what I do in my function even if the function itself runs on a worker thread.

          QMetaObject::invokeMethod is supposed to execute the corresponding slot from the GUI thread

          1 Reply Last reply
          0
          • G Offline
            G Offline
            giesbert
            wrote on last edited by
            #5

            Have you looked where it crashed exactly?
            Do you have a call stack?

            Nokia Certified Qt Specialist.
            Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

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

              [quote author="Tom C" date="1371635338"]That's what I do in my function even if the function itself runs on a worker thread.

              QMetaObject::invokeMethod is supposed to execute the corresponding slot from the GUI thread[/quote]

              This invokes a slot that directly manipulates the widget (i.e. GUI stuff).
              @
              QMetaObject::invokeMethod(w,"setText", Qt::QueuedConnection,Q_ARG(QString,arg));
              @

              What you have to do is invoke a custom slot you have to implement for example in a wrapper or subclass for your widget. And in this slot you can then call the setText() slot.
              @
              QMetaObject::invokeMethod(myWidgetPointer,"myCustomChangeTextSlot", Qt::QueuedConnection,Q_ARG(QString,arg));

              MyWidget::myCustomChangeTextSlot(QString a_text)
              {
              setText(a_text); // in case of subclass
              m_widget->setText(a_text); // in case of wrapper class
              }
              @

              1 Reply Last reply
              0
              • raven-worxR Offline
                raven-worxR Offline
                raven-worx
                Moderators
                wrote on last edited by
                #7

                i don't see any advantage/difference in your solution KA51O??

                --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                If you have a question please use the forum so others can benefit from the solution in the future

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

                  The advantage is that his doesn't work because you cannot manipulate GUI stuff like widgets from outside of the GUI thread and mine works because the manipulating call is issued from within the GUI thread. Just as sierdzio already pointed out.

                  Atleast thats what I thought the problem was all about?

                  1 Reply Last reply
                  0
                  • raven-worxR Offline
                    raven-worxR Offline
                    raven-worx
                    Moderators
                    wrote on last edited by
                    #9

                    since he used a queued-connection i will be executed in the thread of the widget (gui thread) and not from his worker-thread... or do i miss something?!

                    i would also like to see the call stack of the crash please. And are you sure that w is a valid pointer?

                    --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                    If you have a question please use the forum so others can benefit from the solution in the future

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

                      well obviously not otherwise why would it crash.
                      Edit: I'm not so sure about this myself, but I think the GUI manipulating call is not allowed to be triggered from a none GUI thread. The QueuedConnection in this case does not change the fact that its triggered from outside.

                      1 Reply Last reply
                      0
                      • raven-worxR Offline
                        raven-worxR Offline
                        raven-worx
                        Moderators
                        wrote on last edited by
                        #11

                        [quote author="KA51O" date="1371643135"]well obviously not otherwise why would it crash.[/quote]
                        thats excatly the question ... to me it's not that obvious that this is the reason. Even without haven seen the call stack.

                        --- SUPPORT REQUESTS VIA CHAT WILL BE IGNORED ---
                        If you have a question please use the forum so others can benefit from the solution in the future

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

                          if you would do this in the setText() method you would see that sender and receiver are in different threads.
                          @
                          currentThread =this->thread();
                          senderThread = QObject::sender()->thread();
                          if(currentThread != senderThread)
                          {
                          //complain by either failing an assert or printing a warning or something
                          }
                          @
                          And I think that's what's done somewhere inside to check that GUI objects are not manipulated from outside of the GUI thread.

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

                            For example this check is done in QCoreApplication. I think there's something similar for GUI objects.
                            @
                            void QCoreApplicationPrivate::checkReceiverThread(QObject *receiver)
                            {
                            QThread *currentThread = QThread::currentThread();
                            QThread *thr = receiver->thread();
                            Q_ASSERT_X(currentThread == thr || !thr,
                            "QCoreApplication::sendEvent",
                            QString::fromLatin1("Cannot send events to objects owned by a different thread. "
                            "Current thread %1. Receiver '%2' (of type '%3') was created in thread %4")
                            .arg(QString::number((quintptr) currentThread, 16))
                            .arg(receiver->objectName())
                            .arg(QLatin1String(receiver->metaObject()->className()))
                            .arg(QString::number((quintptr) thr, 16))
                            .toLocal8Bit().data());
                            Q_UNUSED(currentThread);
                            Q_UNUSED(thr);
                            }
                            @

                            1 Reply Last reply
                            0
                            • G Offline
                              G Offline
                              giesbert
                              wrote on last edited by
                              #14

                              QueuedConnection is used to emit across thread boundaries.
                              This will not crash due to thread boundaries and invoking with this parameter doies the same as emitting a signal in a thread and connecting it by autoconnect to an object in another thread.

                              Nokia Certified Qt Specialist.
                              Programming Is Like Sex: One mistake and you have to support it for the rest of your life. (Michael Sinz)

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

                                [quote author="Gerolf" date="1371644612"]QueuedConnection is used to emit across thread boundaries.
                                This will not crash due to thread boundaries and invoking with this parameter doies the same as emitting a signal in a thread and connecting it by autoconnect to an object in another thread.[/quote]

                                I know but the problem is not with QueuedConnection but with the fact that the slot that the signal is connected to is a slot that results in a GUI object being manipultated (e.g. QLabel::setText()).

                                What I mean is that this is ok.
                                @
                                //object of this class lifes in main thread
                                class MyClass : public QObject
                                {
                                Q_OBJECT
                                public slots:
                                void setText(QString a_text);
                                private:
                                QString m_text;
                                };

                                void MyClass:setText(QString a_text)
                                {
                                m_text = a_text;
                                }

                                MyClass * pointerToMyClassObject = new MyClass ();

                                //somewhere outside of main thread
                                QMetaObject::invokeMethod(pointerToMyClassObject,"setText", Qt::QueuedConnection,Q_ARG(QString,arg));
                                @

                                But this is not ok
                                @
                                // living in the context of the main thread
                                QLabel* pointerToQLabelObject = new QLabel();

                                //somewhere outside of main thread
                                QMetaObject::invokeMethod(pointerToQLabelObject,"setText", Qt::QueuedConnection,Q_ARG(QString,arg));
                                @

                                1 Reply Last reply
                                0
                                • JKSHJ Online
                                  JKSHJ Online
                                  JKSH
                                  Moderators
                                  wrote on last edited by
                                  #16

                                  [quote author="Tom C" date="1371634772"]
                                  @
                                  //I call a factory to create a QLabel object from the GUI thread (Blocking call)
                                  w = viewFactory()->createView("label");
                                  @
                                  [/quote]Hi Tom, are you sure the QLabel is created in the GUI thread? Can you post the code for createView()?

                                  [quote author="KA51O" date="1371645076"]...the problem is not with QueuedConnection but with the fact that the slot that the signal is connected to is a slot that results in a GUI object being manipultated (e.g. QLabel::setText()).[/quote]Hi KA51O, please see http://qt-project.org/forums/viewthread/29030/ for my response to this.

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

                                  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