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 Memory Management

QFutureWatcher Memory Management

Scheduled Pinned Locked Moved Solved General and Desktop
6 Posts 3 Posters 2.8k 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.
  • R Offline
    R Offline
    rtavakko
    wrote on last edited by rtavakko
    #1

    Hi guys,

    This is more of a C++ question but with QT classes.

    I recently learned about the magic of using QFuture, QFutureWatcher and lambda functions to cheat the signal / slot system :)

    As an example I have this code which works perfectly. I can pass any parameters through my lambda function.

    QFutureWatcher<void>* watcher = new QFutureWatcher<void>;
    QFuture<void> future;
    
    QObject::connect(watcher,&QFutureWatcher<void>::finished,[=](){threadFinished(0,watcher);});
    
    future = QtConcurrent::run(this,&MainWindow::threadedFunction, 0);
    
    watcher->setFuture(future);
    
    void MainWindow::threadedFunction(int num)
    {
        qDebug() << "RUNNING:[" << num << "]\n";
        return;
    }
    
    void MainWindow::threadFinished(int num, QFutureWatcher<void>* watcher)
    {
        qDebug() << "FINISHED:[" << num << "]\n";
        qDebug() << watcher;
    }
    

    Looking at this thread there is no other way to make this work other than initializing a QFutureWatcher pointer since if don't use the 'new' keyword, the object goes out of scope and gets deleted before it fires its 'finished' signal:

    https://www.qtcentre.org/threads/21670-QFutureWatcher-finished()-signal-not-working

    This means I have to either include the QFutureWatcher as part of my class definition or pass it through the lambda function to my 'threadFinished' function and delete it there.

    I wanted to confirm that there is no way around this and I have to use the 'new' keyword every time? From the documentation example it seems that you shouldn't have to do this:

    https://doc.qt.io/qt-5/qfuturewatcher.html

    Thanks a lot

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by
      #2

      hi
      The examples are showing the usage of the class
      and are not so concerned about scope issue.

      So the normal solution with asynchronous API/classes like
      QNetworkManager / QFutureWatcher and is to either new it, or have as part of a class so it will outlive the function call.

      R 1 Reply Last reply
      3
      • mrjjM mrjj

        hi
        The examples are showing the usage of the class
        and are not so concerned about scope issue.

        So the normal solution with asynchronous API/classes like
        QNetworkManager / QFutureWatcher and is to either new it, or have as part of a class so it will outlive the function call.

        R Offline
        R Offline
        rtavakko
        wrote on last edited by
        #3

        @mrjj Got it. Since QFutureWatcher inherits QObject, it also sounds like connecting 'finished' to 'deleteLater' is a solution but from what I just ran it keeps sitting there like its paying rent. Do you have any thoughts on this?

        I think I'll just pass the pointer to my result handler and delete it there if nothing else works out.

        1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by
          #4

          Hi
          Hmm. That should actually have worked.
          ( 'finished' -> 'deleteLater)
          Capturing the pointer and handled it there should be fine
          but deletelater would been slightly more elegant. :)

          1 Reply Last reply
          3
          • Chris KawaC Offline
            Chris KawaC Offline
            Chris Kawa
            Lifetime Qt Champion
            wrote on last edited by
            #5

            Connecting finished to deleteLater should work. Maybe the task is not actually finishing?

            Passing watcher into the handler unnecessarily complicates the function IMO and kinda mixes responsibilities. You could just delete it in the lambda instead.
            Speaking of lambdas, it's a good idea to give the connection the third parameter - the object ( I guess this in the example code). Otherwise you're running a risk of this being deleted before the watcher and then the lambda would crash trying to call threadFinished() on a deleted object.

            1 Reply Last reply
            3
            • R Offline
              R Offline
              rtavakko
              wrote on last edited by
              #6

              @mrjj @Chris-Kawa I just ran it again, it does work. I was checking if it was set to NULL right when I received 'destroyed' which is sent right before deletion... I was too impatient...

              Also deleting in lambda works as you said and makes more sense. Either way I think both are clean ways of doing this.

              I'll pass 'this' to it also, its just that I'd seen people do it without passing the object.

              Either way this would be the updated connection:

              QObject::connect(watcher,&QFutureWatcher<void>::finished,this,[=](){this->threadFinished(0,watcher);delete watcher;});
              

              And this confirms deletion:

              QObject::connect(watcher,&QFutureWatcher<void>::destroyed,this,[=](){qDebug() << "DELETED WATCHER";});
              

              Thanks for the quick responses guys!

              1 Reply Last reply
              2

              • Login

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