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. QFutureWatcher's signal finished does not get emitted.
QtWS25 Last Chance

QFutureWatcher's signal finished does not get emitted.

Scheduled Pinned Locked Moved Unsolved General and Desktop
qfuturewatchersignals&slotsfinished
16 Posts 5 Posters 6.1k 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.
  • 0 Offline
    0 Offline
    0xedd1e
    wrote on 8 Dec 2017, 22:15 last edited by
    #1

    Initial note
    I've started on revamping a project that was initially was written using QT 5.4, and which worked just fine back then regarding signals and slots mentioned in the topic.

    ScriptEngine allocates ScriptInstances and then kickstarts them using start() method.

    Problem
    QFutureWatcher::finished() signal never seems to be emitted in my case, meaning that ScriptInstance::slotFinished() never gets executed, and there is no information pointing me in any direction of what may be wrong since there are no warnings compile time nor runtime.

    I have debugged the code and seen that the RunFunctionTask<void>::run() method calls this->reportFinished(); upon task completion but still no signal gets emitted.

    I'm currently using the latest version of QT (community edition) 5.9.3 with GCC kit running on Fedora 27. Installation of QT was made using the installer (i.e. not using Fedoras own package management).

    Any idea what may be wrong?

    Class (with necessary methods left):

    class ScriptInstance : public QObject
    {
        Q_OBJECT
      public:
        explicit ScriptInstance(const quint32& scriptInstanceId, const QString& scriptSource, const QString& scriptFileName, const QMap<QString, QVariant>& scriptArguments = QMap<QString, QVariant>{}, int scriptStartLine = 1);
    
        /**
         * @brief start - Method responsible for kickstarting the script instance.
         */
        void start();
    
        /**
         * @brief scriptExecutionThread - Worker thread that will be responsible for executing the requested script (in the background).
         */
        void scriptExecutionThread();
    
      public slots:
        /**
         * @brief slotFinished - Receiving method responsible for reporting back to ScriptEngine that execution is finished.
         */
        void slotFinished();
    
      signals:
        void signalDispose(quint32 scriptInstanceId);
    
      private:
        quint32 _scriptInstanceId;
        QString _scriptSource;
        QString _scriptFileName;
        QMap<QString, QVariant> _scriptArguments;
        int _scriptStartLine;
        QFuture<void> _scriptFuture;
        QFutureWatcher<void> _scriptWatcher;
    }
    

    Implementation:

    ScriptInstance::ScriptInstance(const quint32& scriptInstanceId, const QString& scriptSource, const QString& scriptFileName, const QMap<QString, QVariant>& scriptArguments, int scriptStartLine)
      :_scriptInstanceId(scriptInstanceId), _scriptSource(scriptSource), _scriptFileName(scriptFileName), _scriptArguments(scriptArguments), _scriptStartLine(scriptStartLine)
    {
    }
    
    void ScriptInstance::start()
    {
      qInfo() << "Executing script " << _scriptFileName << " (" << _scriptInstanceId << ")";
      connect(&_scriptWatcher, &QFutureWatcher<void>::finished, this, &ScriptInstance::slotFinished);
      _scriptFuture = QtConcurrent::run(this, &ScriptInstance::scriptExecutionThread);
      _scriptWatcher.setFuture(_scriptFuture);
    }
    
    void ScriptInstance::scriptExecutionThread()
    {
      QThread::sleep(10); // My task is a bit more fun, but for this presentation this should do. 
    }
    
    void ScriptInstance::slotFinished()
    {
      try
      {
        qInfo() << "Execution of script " << _scriptFileName << " (" << _scriptInstanceId << ") has ended.";
        // If there was any errors (i.e. exception thrown) during script execution,
        // then we'll need to transfer those exceptions from execution thread (http://doc.qt.io/qt-5/qexception.html)
        _scriptWatcher.future().waitForFinished();
        emit signalDispose(_scriptInstanceId);
      }
      catch(...)
      {
        emit signalDispose(_scriptInstanceId);
        throw;
      }
    }
    
    1 Reply Last reply
    0
    • V Offline
      V Offline
      VRonin
      wrote on 11 Dec 2017, 09:23 last edited by
      #2

      2 possible problems come to mind:

      • you call start twice, binding _scriptWatcher to another _scriptFuture
      • you are blocking the event loop in the main thread (a while(true) or something similar)

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      0 1 Reply Last reply 14 Dec 2017, 15:27
      1
      • V VRonin
        11 Dec 2017, 09:23

        2 possible problems come to mind:

        • you call start twice, binding _scriptWatcher to another _scriptFuture
        • you are blocking the event loop in the main thread (a while(true) or something similar)
        0 Offline
        0 Offline
        0xedd1e
        wrote on 14 Dec 2017, 15:27 last edited by
        #3

        @VRonin
        I'm sorry to say that neither of the scenarions you mention occurs;

        1. start() is only called once per instance.
        2. Main thread is not blocked/hogged, the application as a whole is still responsive (including UI so such events gets processed just fine).

        Since last time I've bumped the QT version from 5.9.3 to 5.10 but the issue still remains.

        Any more ideas?

        1 Reply Last reply
        0
        • V Offline
          V Offline
          VRonin
          wrote on 14 Dec 2017, 17:03 last edited by
          #4

          Ok, then let's make a slight change, lets move away from QtConcurrent and just use C++:

          void ScriptInstance::start()
          {
          qInfo() << "Executing script " << _scriptFileName << " (" << _scriptInstanceId << ")";
          QObject* signalObj = new QObject;
          connect(signalObj , &QObject::destroyed, this, &ScriptInstance::slotFinished);
          std::async(std::launch::async,[=]()->void{scriptExecutionThread(); delete signalObj;});
          }
          

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          0 1 Reply Last reply 16 Dec 2017, 21:19
          0
          • V VRonin
            14 Dec 2017, 17:03

            Ok, then let's make a slight change, lets move away from QtConcurrent and just use C++:

            void ScriptInstance::start()
            {
            qInfo() << "Executing script " << _scriptFileName << " (" << _scriptInstanceId << ")";
            QObject* signalObj = new QObject;
            connect(signalObj , &QObject::destroyed, this, &ScriptInstance::slotFinished);
            std::async(std::launch::async,[=]()->void{scriptExecutionThread(); delete signalObj;});
            }
            
            0 Offline
            0 Offline
            0xedd1e
            wrote on 16 Dec 2017, 21:19 last edited by
            #5

            @VRonin
            I've now tested your example and ScriptInstance::slotFinished() is still not called. I also have stepped through the deallocation of the signalObj in start() while having breakpoints set in the MOC-code, but still no luck.

            moc_ScriptInstance.cpp (part of it):

            void ScriptInstance::qt_static_metacall(QObject *_o, QMetaObject::Call _c, int _id, void **_a)
            {
                if (_c == QMetaObject::InvokeMetaMethod) {
                    ScriptInstance *_t = static_cast<ScriptInstance *>(_o);
                    Q_UNUSED(_t)
                    switch (_id) {
                    case 0: _t->signalDispose((*reinterpret_cast< quint32(*)>(_a[1]))); break;
                    case 1: _t->slotFinished(); break;  // <-- Never called..
            

            Any idea where to look to see where all the invokes/function pointers gets registered, to be able to see if any entry for slotFinished is left out or not, or any other suggestions?

            PS. I really appreciate your input!

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on 16 Dec 2017, 21:39 last edited by
              #6

              Hi,

              What about calling signalObj->deleteLater() in place of delete?

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              0 1 Reply Last reply 16 Dec 2017, 22:03
              0
              • SGaistS SGaist
                16 Dec 2017, 21:39

                Hi,

                What about calling signalObj->deleteLater() in place of delete?

                0 Offline
                0 Offline
                0xedd1e
                wrote on 16 Dec 2017, 22:03 last edited by
                #7

                @SGaist
                I've just tried that and slotFinished() is still not called.

                mrjjM 1 Reply Last reply 16 Dec 2017, 22:34
                0
                • 0 0xedd1e
                  16 Dec 2017, 22:03

                  @SGaist
                  I've just tried that and slotFinished() is still not called.

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on 16 Dec 2017, 22:34 last edited by
                  #8

                  @0xedd1e
                  Hi
                  Are you running ScriptInstance in another thread? (movetothread style)
                  Have you checked you can emit a signal and have a slot called in the class ?
                  ( or the actual worker thread if that is the case)

                  I tried Wielands code in main thread and it worked so i wondering
                  if its something with emitting signals from your actual code.
                  (clearly it is but i mean in general)

                  So forget about async/QFutureWatcher for a moment and simply emit a signal to a slot
                  on same level/class/interclass as the QFutureWatcher is running.

                  Sorry if you already validated other signals do work. It was just a thought.

                  0 1 Reply Last reply 16 Dec 2017, 22:57
                  2
                  • mrjjM mrjj
                    16 Dec 2017, 22:34

                    @0xedd1e
                    Hi
                    Are you running ScriptInstance in another thread? (movetothread style)
                    Have you checked you can emit a signal and have a slot called in the class ?
                    ( or the actual worker thread if that is the case)

                    I tried Wielands code in main thread and it worked so i wondering
                    if its something with emitting signals from your actual code.
                    (clearly it is but i mean in general)

                    So forget about async/QFutureWatcher for a moment and simply emit a signal to a slot
                    on same level/class/interclass as the QFutureWatcher is running.

                    Sorry if you already validated other signals do work. It was just a thought.

                    0 Offline
                    0 Offline
                    0xedd1e
                    wrote on 16 Dec 2017, 22:57 last edited by
                    #9

                    @mrjj
                    I've now done the following;

                    1. Added a new signal, signalDebug(), to ScriptInstance class.
                    2. Connected signalDebug() to slot slotFinished() in the constructor for ScriptInstance class.
                    3. In ScriptInstance::scriptExecutionThread() I emitted the signalDebug() signal.

                    Result: slotFinished() is called just fine.

                    FYI: I'm also back to using QtConcurrent mechanisms.

                    mrjjM 1 Reply Last reply 17 Dec 2017, 10:36
                    1
                    • 0 0xedd1e
                      16 Dec 2017, 22:57

                      @mrjj
                      I've now done the following;

                      1. Added a new signal, signalDebug(), to ScriptInstance class.
                      2. Connected signalDebug() to slot slotFinished() in the constructor for ScriptInstance class.
                      3. In ScriptInstance::scriptExecutionThread() I emitted the signalDebug() signal.

                      Result: slotFinished() is called just fine.

                      FYI: I'm also back to using QtConcurrent mechanisms.

                      mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on 17 Dec 2017, 10:36 last edited by mrjj
                      #10

                      @0xedd1e
                      Ok, so signals seems to work.
                      I was wondering if you needed to specify connection type
                      but if some signals work, all should.

                      but just for test
                      connect(&_scriptWatcher, &QFutureWatcher<void>::finished, this, &ScriptInstance::slotFinished, Qt::QueuedConnection);

                      Else Im a bit out of idea as all seem ok.

                      Update
                      I ran your code and slotFinished was called ?
                      Can you try it
                      https://www.dropbox.com/s/rhdk6xxk323ziqh/test_thread.zip?dl=0

                      alt text

                      0 1 Reply Last reply 17 Dec 2017, 11:24
                      1
                      • mrjjM mrjj
                        17 Dec 2017, 10:36

                        @0xedd1e
                        Ok, so signals seems to work.
                        I was wondering if you needed to specify connection type
                        but if some signals work, all should.

                        but just for test
                        connect(&_scriptWatcher, &QFutureWatcher<void>::finished, this, &ScriptInstance::slotFinished, Qt::QueuedConnection);

                        Else Im a bit out of idea as all seem ok.

                        Update
                        I ran your code and slotFinished was called ?
                        Can you try it
                        https://www.dropbox.com/s/rhdk6xxk323ziqh/test_thread.zip?dl=0

                        alt text

                        0 Offline
                        0 Offline
                        0xedd1e
                        wrote on 17 Dec 2017, 11:24 last edited by
                        #11

                        @mrjj
                        Once I discovered the issue I experimented with different type of connections, but no change in behavior.

                        The project you provided works just fine, so I guess that rules out that there is no issue(s) related to my setup at least.

                        The ScriptEngine in my case is a singleton, but I don't see why that should matter in this case since all other signals/slots seems to work just fine.

                        mrjjM 1 Reply Last reply 17 Dec 2017, 11:36
                        0
                        • 0 0xedd1e
                          17 Dec 2017, 11:24

                          @mrjj
                          Once I discovered the issue I experimented with different type of connections, but no change in behavior.

                          The project you provided works just fine, so I guess that rules out that there is no issue(s) related to my setup at least.

                          The ScriptEngine in my case is a singleton, but I don't see why that should matter in this case since all other signals/slots seems to work just fine.

                          mrjjM Offline
                          mrjjM Offline
                          mrjj
                          Lifetime Qt Champion
                          wrote on 17 Dec 2017, 11:36 last edited by
                          #12

                          @0xedd1e
                          Ok. super. Yes it means nothing wrong inside Qt/the setup.

                          • ScriptEngine in my case is a singleton

                          meaning its static ?

                          But I agree if other signals can get be emitted (from same nesting level) then
                          it seems unlikely its that.

                          0 1 Reply Last reply 17 Dec 2017, 14:25
                          0
                          • mrjjM mrjj
                            17 Dec 2017, 11:36

                            @0xedd1e
                            Ok. super. Yes it means nothing wrong inside Qt/the setup.

                            • ScriptEngine in my case is a singleton

                            meaning its static ?

                            But I agree if other signals can get be emitted (from same nesting level) then
                            it seems unlikely its that.

                            0 Offline
                            0 Offline
                            0xedd1e
                            wrote on 17 Dec 2017, 14:25 last edited by
                            #13

                            @mrjj
                            Correct, it is static.

                            I'm really out of ideas, so I guess I have to go back to earlier changesets within my project and see if I can pinpoint the exact change that caused this behavior. However, the code connected to the script engine and script instance hasn't changed for quite a while though, so I'll try to back the project to an earlier changeset and see if there are changes elsewhere that causes this. I registered a bug in my own ticket system when I discovered this issue but marked it for check-later-when-qt-upgrades since it worked fine in QT 5.4 and earlier.

                            Thanks again for all the feedback and I'll report back during the upcoming holiday.

                            0 1 Reply Last reply 17 Dec 2017, 16:23
                            0
                            • 0 0xedd1e
                              17 Dec 2017, 14:25

                              @mrjj
                              Correct, it is static.

                              I'm really out of ideas, so I guess I have to go back to earlier changesets within my project and see if I can pinpoint the exact change that caused this behavior. However, the code connected to the script engine and script instance hasn't changed for quite a while though, so I'll try to back the project to an earlier changeset and see if there are changes elsewhere that causes this. I registered a bug in my own ticket system when I discovered this issue but marked it for check-later-when-qt-upgrades since it worked fine in QT 5.4 and earlier.

                              Thanks again for all the feedback and I'll report back during the upcoming holiday.

                              0 Offline
                              0 Offline
                              0xedd1e
                              wrote on 17 Dec 2017, 16:23 last edited by
                              #14

                              @0xedd1e said in QFutureWatcher's signal finished does not get emitted.:

                              @mrjj
                              Correct, it is static.

                              I'm really out of ideas, so I guess I have to go back to earlier changesets within my project and see if I can pinpoint the exact change that caused this behavior. However, the code connected to the script engine and script instance hasn't changed for quite a while though, so I'll try to back the project to an earlier changeset and see if there are changes elsewhere that causes this. I registered a bug in my own ticket system when I discovered this issue but marked it for check-later-when-qt-upgrades since it worked fine in QT 5.4 and earlier.

                              Thanks again for all the feedback and I'll report back during the upcoming holiday.

                              FYI;
                              I've now gone back and tested previous versions of the project but can't seem to get it working in any of the earlier versions now using QT 5.10. So I guess something has changed in QT, but I can't figure out what though and to my knowledge I follow the recommendations according to the documentation of QT.

                              Worth trying going back to using earlier versions of QT?

                              mrjjM 1 Reply Last reply 17 Dec 2017, 16:30
                              0
                              • 0 0xedd1e
                                17 Dec 2017, 16:23

                                @0xedd1e said in QFutureWatcher's signal finished does not get emitted.:

                                @mrjj
                                Correct, it is static.

                                I'm really out of ideas, so I guess I have to go back to earlier changesets within my project and see if I can pinpoint the exact change that caused this behavior. However, the code connected to the script engine and script instance hasn't changed for quite a while though, so I'll try to back the project to an earlier changeset and see if there are changes elsewhere that causes this. I registered a bug in my own ticket system when I discovered this issue but marked it for check-later-when-qt-upgrades since it worked fine in QT 5.4 and earlier.

                                Thanks again for all the feedback and I'll report back during the upcoming holiday.

                                FYI;
                                I've now gone back and tested previous versions of the project but can't seem to get it working in any of the earlier versions now using QT 5.10. So I guess something has changed in QT, but I can't figure out what though and to my knowledge I follow the recommendations according to the documentation of QT.

                                Worth trying going back to using earlier versions of QT?

                                mrjjM Offline
                                mrjjM Offline
                                mrjj
                                Lifetime Qt Champion
                                wrote on 17 Dec 2017, 16:30 last edited by
                                #15

                                @0xedd1e
                                Hi I also looked at the release notes to see
                                if something with Future/Concurrent was changed but nothing popped up.

                                • Worth trying going back to using earlier versions of QT?

                                Well for test. it would be a good test if exact same code just works in say 5.6
                                and not in 5.10. But being stucked at 5.4 would be not so optimal.

                                A note about the static.
                                Just to be sure. the class that expects the Finished signal is a static member of some other class?
                                As far as i can recall, you cant compile if you try to connect to a static class slot so im inclided to
                                say that is not the issue.

                                Since your mini sample works. There must be some difference in the real code. But i cant
                                think of more to check.

                                1 Reply Last reply
                                0
                                • L Offline
                                  L Offline
                                  leochan2009
                                  wrote on 26 Jan 2021, 02:35 last edited by
                                  #16

                                  same issue i have came across; see my post:
                                  https://forum.qt.io/topic/122640/qvideoprobe-stop-working-when-processing-time-is-long/11

                                  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