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() problem
Forum Updated to NodeBB v4.3 + New Features

QMetaObject::invokeMethod() problem

Scheduled Pinned Locked Moved Unsolved General and Desktop
10 Posts 4 Posters 1.0k 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.
  • PerdrixP Offline
    PerdrixP Offline
    Perdrix
    wrote on last edited by Perdrix
    #1

    Given:

    public:
    	void Progress1(const QString& szText, int lAchieved1);
    protected slots:
    	virtual void slotProgress1(const QString& szText, int lAchieved1);
    

    and:

    void ProgressBase::Progress1(const QString& text, int achieved)
    {
    	QMetaObject::invokeMethod(this, "slotProgress1", Qt::QueuedConnection,
    		Q_ARG(const QString&, text),
    		Q_ARG(int, achieved));
    }
    
    void ProgressBase::slotProgress1(const QString& szText, int lAchieved1)
    {
            qDebug() << __FUNCTION__;   // etc.
    
    

    If Progress1 is called from a long running non-GUI thread, all is well and the slot is driven.

    If however Progress1 is called from long running code on the GUI thread, then the slot isn't driven because the event dispatcher doesn't get to handle it.

    What's the correct way to ensure the slot is driven regardless of which thread Progess1 is called from? Calling QCoreApplication::processEvents() inside Progress1 immediately after invokeMethod() when the code isn't the GUI thread doesn't feel like it's the correct answer.

    JoeCFDJ Christian EhrlicherC 2 Replies Last reply
    0
    • PerdrixP Perdrix deleted this topic on
    • PerdrixP Perdrix restored this topic on
    • PerdrixP Perdrix

      Given:

      public:
      	void Progress1(const QString& szText, int lAchieved1);
      protected slots:
      	virtual void slotProgress1(const QString& szText, int lAchieved1);
      

      and:

      void ProgressBase::Progress1(const QString& text, int achieved)
      {
      	QMetaObject::invokeMethod(this, "slotProgress1", Qt::QueuedConnection,
      		Q_ARG(const QString&, text),
      		Q_ARG(int, achieved));
      }
      
      void ProgressBase::slotProgress1(const QString& szText, int lAchieved1)
      {
              qDebug() << __FUNCTION__;   // etc.
      
      

      If Progress1 is called from a long running non-GUI thread, all is well and the slot is driven.

      If however Progress1 is called from long running code on the GUI thread, then the slot isn't driven because the event dispatcher doesn't get to handle it.

      What's the correct way to ensure the slot is driven regardless of which thread Progess1 is called from? Calling QCoreApplication::processEvents() inside Progress1 immediately after invokeMethod() when the code isn't the GUI thread doesn't feel like it's the correct answer.

      JoeCFDJ Offline
      JoeCFDJ Offline
      JoeCFD
      wrote on last edited by JoeCFD
      #2

      @Perdrix I often use QMetaObject::invokeMethod to trigger a signal. Since slotProgress1 is a slot, you may try to invoke a signal which connects to it in a GUI thread.

      PerdrixP 1 Reply Last reply
      0
      • JoeCFDJ JoeCFD

        @Perdrix I often use QMetaObject::invokeMethod to trigger a signal. Since slotProgress1 is a slot, you may try to invoke a signal which connects to it in a GUI thread.

        PerdrixP Offline
        PerdrixP Offline
        Perdrix
        wrote on last edited by
        #3

        @JoeCFD Maybe I need to ask how can I determine if the thread that invokes Progress1 is the GUI thread and invoke QCoreApplication::processEvents() IF it is is the GUI thread??

        If Progress1 is called from a non-GUI thread then no need to call processEvents() I think?

        D.

        JoeCFDJ 1 Reply Last reply
        0
        • PerdrixP Perdrix

          @JoeCFD Maybe I need to ask how can I determine if the thread that invokes Progress1 is the GUI thread and invoke QCoreApplication::processEvents() IF it is is the GUI thread??

          If Progress1 is called from a non-GUI thread then no need to call processEvents() I think?

          D.

          JoeCFDJ Offline
          JoeCFDJ Offline
          JoeCFD
          wrote on last edited by JoeCFD
          #4

          @Perdrix if you invoke a signal, you do not need to call processEvents() ; slot slotProgress1 is a function and can be called because of a signal or QMetaObject::invokeMethod or direct call. You may check which sender the caller is by calling sender() function inside the slot slotProgress1() .

          void slotProgress1(const QString& szText, int lAchieved1) 
          {
                auto which_sender = sender();
          }
          
          PerdrixP 1 Reply Last reply
          0
          • PerdrixP Perdrix

            Given:

            public:
            	void Progress1(const QString& szText, int lAchieved1);
            protected slots:
            	virtual void slotProgress1(const QString& szText, int lAchieved1);
            

            and:

            void ProgressBase::Progress1(const QString& text, int achieved)
            {
            	QMetaObject::invokeMethod(this, "slotProgress1", Qt::QueuedConnection,
            		Q_ARG(const QString&, text),
            		Q_ARG(int, achieved));
            }
            
            void ProgressBase::slotProgress1(const QString& szText, int lAchieved1)
            {
                    qDebug() << __FUNCTION__;   // etc.
            
            

            If Progress1 is called from a long running non-GUI thread, all is well and the slot is driven.

            If however Progress1 is called from long running code on the GUI thread, then the slot isn't driven because the event dispatcher doesn't get to handle it.

            What's the correct way to ensure the slot is driven regardless of which thread Progess1 is called from? Calling QCoreApplication::processEvents() inside Progress1 immediately after invokeMethod() when the code isn't the GUI thread doesn't feel like it's the correct answer.

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

            @Perdrix said in QMetaObject::invokeMethod() problem:

            If however Progress1 is called from long running code on the GUI thread, then the slot isn't driven because the event dispatcher doesn't get to handle it.

            Then don't use Qt::QueuedConnection so it get's called immediatelly.

            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
            3
            • JoeCFDJ JoeCFD

              @Perdrix if you invoke a signal, you do not need to call processEvents() ; slot slotProgress1 is a function and can be called because of a signal or QMetaObject::invokeMethod or direct call. You may check which sender the caller is by calling sender() function inside the slot slotProgress1() .

              void slotProgress1(const QString& szText, int lAchieved1) 
              {
                    auto which_sender = sender();
              }
              
              PerdrixP Offline
              PerdrixP Offline
              Perdrix
              wrote on last edited by
              #6

              @JoeCFD said in QMetaObject::invokeMethod() problem:

              sender

              So are you saying that Progress1 should simply be declared as a signal ? I can certainly do that ...

              JoeCFDJ Chris KawaC 2 Replies Last reply
              0
              • PerdrixP Perdrix

                @JoeCFD said in QMetaObject::invokeMethod() problem:

                sender

                So are you saying that Progress1 should simply be declared as a signal ? I can certainly do that ...

                JoeCFDJ Offline
                JoeCFDJ Offline
                JoeCFD
                wrote on last edited by JoeCFD
                #7

                @Perdrix I did not mean that. I saw that you are trying to call slotProgress1 with QMetaObject::invokeMethod. What I meant was you may have defined a signal which connects to slot slotProgress1. Instead of trying to trigger the slotProgress1, you can also trigger this signal with QMetaObject::invokeMethod and then slotProgress1 will be called.

                1 Reply Last reply
                0
                • PerdrixP Perdrix

                  @JoeCFD said in QMetaObject::invokeMethod() problem:

                  sender

                  So are you saying that Progress1 should simply be declared as a signal ? I can certainly do that ...

                  Chris KawaC Offline
                  Chris KawaC Offline
                  Chris Kawa
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @Perdrix As @Christian-Ehrlicher said just remove the Qt::QueuedConnection parameter. It forces the invocation to be queued, whether it's on the same thread or not. If you omit this parameter an auto connection type will be used, meaning that the slot will be called immediately if the target object is in the same thread or queued if on a different one.

                  As a side note - if your problem is that the GUI thread is blocked then you're doing it wrong. You should never block GUI thread and long running tasks should always be executed in worker threads.
                  Calling QCoreApplication::processEvents() is a hack indicating bad app flow design.

                  PerdrixP 1 Reply Last reply
                  3
                  • Chris KawaC Chris Kawa

                    @Perdrix As @Christian-Ehrlicher said just remove the Qt::QueuedConnection parameter. It forces the invocation to be queued, whether it's on the same thread or not. If you omit this parameter an auto connection type will be used, meaning that the slot will be called immediately if the target object is in the same thread or queued if on a different one.

                    As a side note - if your problem is that the GUI thread is blocked then you're doing it wrong. You should never block GUI thread and long running tasks should always be executed in worker threads.
                    Calling QCoreApplication::processEvents() is a hack indicating bad app flow design.

                    PerdrixP Offline
                    PerdrixP Offline
                    Perdrix
                    wrote on last edited by
                    #9

                    @Chris-Kawa >Long running tasks should always be executed in worker threads...

                    I couldn't agree more but when dealing with inherited code, you need to cope with the cases where this isn't being done as they're not always simple to move into a worker thread. That's why this code has to be written to handle both cases.

                    Chris KawaC 1 Reply Last reply
                    0
                    • PerdrixP Perdrix

                      @Chris-Kawa >Long running tasks should always be executed in worker threads...

                      I couldn't agree more but when dealing with inherited code, you need to cope with the cases where this isn't being done as they're not always simple to move into a worker thread. That's why this code has to be written to handle both cases.

                      Chris KawaC Offline
                      Chris KawaC Offline
                      Chris Kawa
                      Lifetime Qt Champion
                      wrote on last edited by
                      #10

                      @Perdrix Ah yes, inherited code. The bane of all existence :)
                      Well, auto connection should work as you want. It will do a direct function call when in the same thread, so it doesn't matter that the event loop is blocked.

                      1 Reply Last reply
                      1

                      • Login

                      • Login or register to search.
                      • First post
                        Last post
                      0
                      • Categories
                      • Recent
                      • Tags
                      • Popular
                      • Users
                      • Groups
                      • Search
                      • Get Qt Extensions
                      • Unsolved