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. Why no SIGNAL from QtFutureWatcher ...?

Why no SIGNAL from QtFutureWatcher ...?

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 3 Posters 1.5k 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.
  • A Offline
    A Offline
    Anonymous_Banned275
    wrote on last edited by
    #1

    I am posting this to ask a simple question , and I do not feel it should be buried at the end of another discussion which was about HOW to actually code "connect".

    This post is NOT about coding "connect" , I just want to know WHY I cannot get expected SIGNAL from QtFutureWatcher / QtFutuure / QtConncurent.

    I can manually emit "started".
    I can verify
    isStarted - obviously it will pass test

    then I remove the "emit ' and get

     START run setFuture   @ line  "2471"
     watcher_new.isStarted() true
     watcher_new.isRunning() true
     watcher_new.isFinished() false
     END run setFuture   @ line  "2488"
    

    so it STARTed , it is RUNNING, it is NOT finished

    but
    I did not get expected SLOT function to run on "started" !
    ( I know the connect is OK , it run fine after posting "emit ')
    It "isRunning" ....

    so if it started and is running why no SIGNAL (on started) ?

    that is my question

    I can verify both states - but QtFutureWatcher does not emit expected 'started" SIGNAL.

    and it does finish !

    why am I not getting the SIGNAL(s) ?

            watcher_new.setFuture(QtConcurrent::run(
                                      std::bind(
                                          hci_inquiry,
                                          dev_id,
                                          len,
                                          max_rsp,
                                          lap,     //NULL,
                                          &ii,
                                          flags)
                                      ));
            emit watcher_new.started();
            qDebug()<<" watcher_new.isStarted()" << watcher_new.isStarted();
            qDebug()<<" watcher_new.isRunning()" << watcher_new.isRunning();
            qDebug()<<" watcher_new.isFinished()" << watcher_new.isFinished();
            qDebug()<<" watcher_new.isStarted()" << watcher_new.isStarted();
            qDebug() <<" END run setFuture " << " @ line " << QString::number(__LINE__);
            //watcher_new->waitForFinished();
    
    1 Reply Last reply
    0
    • fcarneyF Offline
      fcarneyF Offline
      fcarney
      wrote on last edited by
      #2

      @AnneRanch said in Why no SIGNAL from QtFutureWatcher ...?:

      qDebug()<<" watcher_new.isFinished()" << watcher_new.isFinished();

      All I can see is that the concurrent code is not done running by the time you hit this debug statement.
      If you do this does it change the output:

              emit watcher_new.started();
              watcher_new->waitForFinished();
              qDebug()<<" watcher_new.isStarted()" << watcher_new.isStarted();
              qDebug()<<" watcher_new.isRunning()" << watcher_new.isRunning();
              qDebug()<<" watcher_new.isFinished()" << watcher_new.isFinished();
              qDebug()<<" watcher_new.isStarted()" << watcher_new.isStarted();
              qDebug() <<" END run setFuture " << " @ line " << QString::number(__LINE__);
             
      

      You can also tie a function to the signal of the QFutureWatcher::finished to tell you when it completes running the concurrent code.

      C++ is a perfectly valid school of magic.

      1 Reply Last reply
      1
      • C Offline
        C Offline
        ChrisW67
        wrote on last edited by
        #3

        This post is NOT about coding "connect" , I just want to know WHY I cannot get expected SIGNAL from QtFutureWatcher / QtFutuure / QtConncurent.

        It is exactly about that. If do not connect the sender to the receiver correctly (or at all) and manage the lifetimes of these objects then you will never receive signals. You are not receiving a signal because something in your code is incorrect or because object lifetimes are not being managed.

        Here is a single-file example that demonstrates clearly that such signals are sent and received. Feel free to compare it to your code to see where you are going wrong.

        #include <QCoreApplication>
        #include <QObject>
        #include <QTimer>
        #include <QtConcurrent>
        #include <QDebug>
        
        int longRunningWhatnot() {
            qDebug() << "Enter" << Q_FUNC_INFO;
            // Three second delay
            QEventLoop wait;
            QTimer::singleShot(3000, &wait, &QEventLoop::quit);
            wait.exec();
            qDebug() << "Leave" << Q_FUNC_INFO;
            return 42;
        }
        
        class Test: public QObject {
            Q_OBJECT
        public:
            explicit Test(QObject *p = nullptr): QObject(p)   {
                qDebug() << "Enter" << Q_FUNC_INFO;
                watcher = new QFutureWatcher<int>(this);
                connect(watcher, &QFutureWatcher<int>::started,  this, &Test::started);
                connect(watcher, &QFutureWatcher<int>::finished, this, &Test::finished);
                watcher->setFuture(QtConcurrent::run(&longRunningWhatnot));
                qDebug() << "Leave" << Q_FUNC_INFO;
            }
        
            ~Test() { }
        
        private:
            void started()  {
                qDebug() << "Call" << Q_FUNC_INFO;
            }
            void finished() {
                qDebug() << "Call" << Q_FUNC_INFO;
                qDebug() << "Returned" << watcher->result();
            }
        
            QFutureWatcher<int> *watcher;
        };
        
        
        int main(int argc, char *argv[])  {
            QCoreApplication a(argc, argv);
            Test test;
            // ensure program terminates after 10 seconds
            QTimer::singleShot(10000, &a, &QCoreApplication::quit);
            return a.exec();
        }
        
        #include "main.moc"
        

        Output is:

        Enter Test::Test(QObject*)
        Leave Test::Test(QObject*)
        Call void Test::started()
        Enter int longRunningWhatnot()
        Leave int longRunningWhatnot()
        Call void Test::finished()
        Returned 42
        

        BTW: SHOUTING every third word will NOT lead to better responses. Writing straightforward, informative questions will get you a lot further.

        1 Reply Last reply
        4
        • A Offline
          A Offline
          Anonymous_Banned275
          wrote on last edited by
          #4

          I think I realized the cause of my problem.

          Allow me to make another pass on theory.

          QT is an event driven "system /banana"
          The main "object / loop" is wrapper for everything " under it "

          skipping to my next object / loop is my

          MDI - which is another wrapper for my "menu items"
          then comes my "Bluetooth " object / loop/class .
          one of the sub object / loop / classes "push button" task is to
          run (function ), using QtConncurent ) external ( library ) function
          QtConcurrent :run builds additional threads
          AND EXITS
          THEN "PUSH-BUTTON" EXITS

                **THEN THIS EXTERNAL function EXITS (posting "finished" SIGNAL  **  after  about 10 seconds
          

          after the external function is finished , and "finished" SIGNAL is emitted ( it really does not matter by whom at this point of discussion )

          and if they are emitted WHO can receive them ?

          1. The function who defined the "connect" no longer runs
          2. If so - are the newly created threads also terminated"?
          3. Did the newly created threads started in what loop / object ?

          I would appreciate real comments on my theory, I am not fond of the terminology I use and really do not need my terminology challenged.

          Cheers

          Just the fact ma'am...

          1 Reply Last reply
          0
          • fcarneyF Offline
            fcarneyF Offline
            fcarney
            wrote on last edited by fcarney
            #5

            @AnneRanch said in Why no SIGNAL from QtFutureWatcher ...?:

            and if they are emitted WHO can receive them ?

            An object that needs the info. Maybe the parent of push button or the push button itself. You could also run a lambda that creates a dialog to tell the user the function is complete. Or maybe a widget the parent of push button knows about that shows that a process is running in the background.

            Your understanding of the process is sufficient.

            The thread, when the code inside completes, will clean itself up. You should probably lock out the button from being pressed again until it completes. This would require the button to have a function that updates its state when the thread completes. This would be a candidate for something that receives this signal. Also, you have have multiple objects connected to the signal if they need to do different things.

            C++ is a perfectly valid school of magic.

            A 1 Reply Last reply
            0
            • fcarneyF fcarney

              @AnneRanch said in Why no SIGNAL from QtFutureWatcher ...?:

              and if they are emitted WHO can receive them ?

              An object that needs the info. Maybe the parent of push button or the push button itself. You could also run a lambda that creates a dialog to tell the user the function is complete. Or maybe a widget the parent of push button knows about that shows that a process is running in the background.

              Your understanding of the process is sufficient.

              The thread, when the code inside completes, will clean itself up. You should probably lock out the button from being pressed again until it completes. This would require the button to have a function that updates its state when the thread completes. This would be a candidate for something that receives this signal. Also, you have have multiple objects connected to the signal if they need to do different things.

              A Offline
              A Offline
              Anonymous_Banned275
              wrote on last edited by
              #6

              @fcarney I have done that in past - it behaves as expected.

              Here is my latest "guess how it works "

              after button press is detected i run a function - in normal sequence - from top to end...
              I setup hci function values , then i setup for QTConcurrent to "run" the hci function. That includes "connect" to be able to process the hci function results - specifically after QTconcurrent "finishes".
              The purpose / reason for using QTConcurrent - I want the main thread to complete the function started by push button. This is part of application tasks and I do not want to wait for hci to complete and block the main thread. ...

              Reason for "waitForfinished " is strictly a debug code.

              Now here is probable cause of all this contrary of what was discussed in the other thread .

              The "QTConcurent " runs the hci function in another threads, however according to documentation - the "futurewatcher " changes according of current state. That has been verified. on "started" and "running".

              But these are NOT SIGNAL and even is so the QtConcurent call DOES NOT sit there - it done its job starting the hci function and the "push button " function is long terminated. The hci function completes in about 10 seconds and that has been verified - by "wait for finished " debug code .

              The process is out of the "button " function and it is time for SIGNAL - coming from the other threads - to be processed.

              That is NOT happening.
              ... and the "connect" has been verified....

              all this contrary of what was discussed in the other thread .

              If code for "connect" is in main thread -
              does it work when SIGNAL is coming from another thread ?

              I do not know how to verify that.

              i know QtConcurrent generate "finished" but my "connect" is not working...

              At this point of development I am in control of "waiting for the external function" . Adding a code to show that would be superficial.
              I got nothing against lambda but prefer the original KISS approach.

              I just moved all pertinent stuff to class/ object constructor and still not getting startup SIGNAL. But it looks better....
              I;ll change the connect to lambda....

              1 Reply Last reply
              0
              • fcarneyF Offline
                fcarneyF Offline
                fcarney
                wrote on last edited by fcarney
                #7

                @AnneRanch said in Why no SIGNAL from QtFutureWatcher ...?:

                If code for "connect" is in main thread -
                does it work when SIGNAL is coming from another thread ?

                Yes, by default a connection can work across threads. There is a parameter in the connect call to change this behavior, but there is no reason to change from default. The time it won't work is when the objects forming the connection get deleted. So the QtFutureWatcher needs to remain somewhere it does not get destroyed. One strategy is to allocate a QtFutureWatcher with new:

                QtFutureWatcher* watcher = new QtFutureWatcher;
                watcher->connect(watcher, QtFutureWatcher::finished, watcher, QtFutureWatcher::deleteLater);  //  this will manage the memory for you.
                

                All connections will be serviced before the QtFutureWatcher is destroyed. My guess is your watcher gets destroyed when you leave the scope of the button callback. So it cannot signal anything. I think my syntax is correct, but you will have to check.

                Also, the QtFutureWatcher does not exist in the other thread. Whatever it calls does. I don't see you connecting to anything inside the thread in this code. Just the QtFutureWatcher that just manages the future.

                C++ is a perfectly valid school of magic.

                A 1 Reply Last reply
                0
                • fcarneyF fcarney

                  @AnneRanch said in Why no SIGNAL from QtFutureWatcher ...?:

                  If code for "connect" is in main thread -
                  does it work when SIGNAL is coming from another thread ?

                  Yes, by default a connection can work across threads. There is a parameter in the connect call to change this behavior, but there is no reason to change from default. The time it won't work is when the objects forming the connection get deleted. So the QtFutureWatcher needs to remain somewhere it does not get destroyed. One strategy is to allocate a QtFutureWatcher with new:

                  QtFutureWatcher* watcher = new QtFutureWatcher;
                  watcher->connect(watcher, QtFutureWatcher::finished, watcher, QtFutureWatcher::deleteLater);  //  this will manage the memory for you.
                  

                  All connections will be serviced before the QtFutureWatcher is destroyed. My guess is your watcher gets destroyed when you leave the scope of the button callback. So it cannot signal anything. I think my syntax is correct, but you will have to check.

                  Also, the QtFutureWatcher does not exist in the other thread. Whatever it calls does. I don't see you connecting to anything inside the thread in this code. Just the QtFutureWatcher that just manages the future.

                  A Offline
                  A Offline
                  Anonymous_Banned275
                  wrote on last edited by
                  #8

                  @fcarney Just came to same conclusion and have the SIGNAL/SLOT finally working.
                  In retrospect

                  1. Engaging in discussion about new and old "connect" did not solve the problem. The old "connect" give plenty of messages when there is a mismatch. End of story.
                  2. Understanding the relations between layers of "loops/ object/classes "" was the key. Prior to that just following some advises proved to be wrong...
                  3. Debugging multithreaded code is not much fun...and never was
                  4. When outputting too many debug messages one can miss some important
                    ones - I missed connect messages when I originally (!) put them in constructor . After I put them back and actually red them, things improved much,
                    ( 5. My presentation style is my business )

                  I appreciate all the help given by many on this forum.

                  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