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. QTConcurrent returns QFuture but the QFuture object has no WaitForFinished method. How do I wait for the threads to finish
Forum Updated to NodeBB v4.3 + New Features

QTConcurrent returns QFuture but the QFuture object has no WaitForFinished method. How do I wait for the threads to finish

Scheduled Pinned Locked Moved Unsolved General and Desktop
6 Posts 4 Posters 1.6k 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.
  • D Offline
    D Offline
    Daniel Williams
    wrote on last edited by
    #1

    I have a method that is working fine w/o threading and I want to add multi-threading. But, once I add the multi-threading, I can't figure out how to make the method wait for all the threads to finish. With the threading, the method returns immediately and the devices are not updated in time to display properly.

    Working without multi-threading:

    void ConfiguredDevices::updateConfiguredDevicesState() {
        Device *device;
        DeviceListIterator iter(_persistedDevices);
        while (iter.hasNext()) {
           iter.next();
           device = iter.value();
           // Update the device object with the availability.
           device->checkAvailability();
        }
    }
    

    This is what I did to add the multi-threading. I created a QVector to hold the QFuture objects. In the loop I call QtConcurrent and add the QFuture events to the QVector. At the end of the method, I thought I'd just loop through the vector of QFuture objects and call the WaitForFinished method on them. However, the QFuture objects returned from QtConcurrent don't have the WaitForFinished method.

    void ConfiguredDevices::updateConfiguredDevicesState() {
        Device *device;
        DeviceListIterator iter(_persistedDevices);
        QVector<QFuture<void>> watchers;
        while (iter.hasNext()) {
           iter.next();
           device = iter.value();
           //device->checkAvailability();
           watchers.append(QtConcurrent::run((Device*)device, &Device::checkAvailability));
        }
        QVectorIterator<QFuture<void>> watcherIter(watchers);
        while (watcherIter.hasNext()) {
           
        }
    
    
    }
    

    Can you give me some advice on how to add the multi-threading? Am I going down the wrong path?

    JonBJ VRoninV 2 Replies Last reply
    0
    • D Daniel Williams

      I have a method that is working fine w/o threading and I want to add multi-threading. But, once I add the multi-threading, I can't figure out how to make the method wait for all the threads to finish. With the threading, the method returns immediately and the devices are not updated in time to display properly.

      Working without multi-threading:

      void ConfiguredDevices::updateConfiguredDevicesState() {
          Device *device;
          DeviceListIterator iter(_persistedDevices);
          while (iter.hasNext()) {
             iter.next();
             device = iter.value();
             // Update the device object with the availability.
             device->checkAvailability();
          }
      }
      

      This is what I did to add the multi-threading. I created a QVector to hold the QFuture objects. In the loop I call QtConcurrent and add the QFuture events to the QVector. At the end of the method, I thought I'd just loop through the vector of QFuture objects and call the WaitForFinished method on them. However, the QFuture objects returned from QtConcurrent don't have the WaitForFinished method.

      void ConfiguredDevices::updateConfiguredDevicesState() {
          Device *device;
          DeviceListIterator iter(_persistedDevices);
          QVector<QFuture<void>> watchers;
          while (iter.hasNext()) {
             iter.next();
             device = iter.value();
             //device->checkAvailability();
             watchers.append(QtConcurrent::run((Device*)device, &Device::checkAvailability));
          }
          QVectorIterator<QFuture<void>> watcherIter(watchers);
          while (watcherIter.hasNext()) {
             
          }
      
      
      }
      

      Can you give me some advice on how to add the multi-threading? Am I going down the wrong path?

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by
      #2

      @Daniel-Williams

      QFuture objects and call the WaitForFinished method on them. However, the QFuture objects returned from QtConcurrent don't have the WaitForFinished method.

      The method is waitForFinished() (note the lowercase start), and should be there. What do you mean by "don't have the WaitForFinished method"?

      1 Reply Last reply
      1
      • D Daniel Williams

        I have a method that is working fine w/o threading and I want to add multi-threading. But, once I add the multi-threading, I can't figure out how to make the method wait for all the threads to finish. With the threading, the method returns immediately and the devices are not updated in time to display properly.

        Working without multi-threading:

        void ConfiguredDevices::updateConfiguredDevicesState() {
            Device *device;
            DeviceListIterator iter(_persistedDevices);
            while (iter.hasNext()) {
               iter.next();
               device = iter.value();
               // Update the device object with the availability.
               device->checkAvailability();
            }
        }
        

        This is what I did to add the multi-threading. I created a QVector to hold the QFuture objects. In the loop I call QtConcurrent and add the QFuture events to the QVector. At the end of the method, I thought I'd just loop through the vector of QFuture objects and call the WaitForFinished method on them. However, the QFuture objects returned from QtConcurrent don't have the WaitForFinished method.

        void ConfiguredDevices::updateConfiguredDevicesState() {
            Device *device;
            DeviceListIterator iter(_persistedDevices);
            QVector<QFuture<void>> watchers;
            while (iter.hasNext()) {
               iter.next();
               device = iter.value();
               //device->checkAvailability();
               watchers.append(QtConcurrent::run((Device*)device, &Device::checkAvailability));
            }
            QVectorIterator<QFuture<void>> watcherIter(watchers);
            while (watcherIter.hasNext()) {
               
            }
        
        
        }
        

        Can you give me some advice on how to add the multi-threading? Am I going down the wrong path?

        VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by VRonin
        #3

        @Daniel-Williams said in QTConcurrent returns QFuture but the QFuture object has no WaitForFinished method. How do I wait for the threads to finish:

        However, the QFuture objects returned from QtConcurrent don't have the WaitForFinished method.

        They do: http://doc.qt.io/qt-5/qfuture.html#waitForFinished

        The usual method do do what you are trying to do is to use blockingMap but that only supports containers having stl iterators (begin()/end()) and not java style iterators. If _persistedDevices supports std::begin/std::end then you can use:

        void ConfiguredDevices::updateConfiguredDevicesState() {
        QtConcurrent::blockingMap(std::begin(_persistedDevices),std::end(_persistedDevices),[](Device *device)->void{device->checkAvailability();});
        }
        

        or using C++17:

        std::for_each(std::execution::par,std::begin(_persistedDevices),std::end(_persistedDevices),[](Device *device)->void{device->checkAvailability();});
        }
        

        "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

        D 2 Replies Last reply
        3
        • VRoninV VRonin

          @Daniel-Williams said in QTConcurrent returns QFuture but the QFuture object has no WaitForFinished method. How do I wait for the threads to finish:

          However, the QFuture objects returned from QtConcurrent don't have the WaitForFinished method.

          They do: http://doc.qt.io/qt-5/qfuture.html#waitForFinished

          The usual method do do what you are trying to do is to use blockingMap but that only supports containers having stl iterators (begin()/end()) and not java style iterators. If _persistedDevices supports std::begin/std::end then you can use:

          void ConfiguredDevices::updateConfiguredDevicesState() {
          QtConcurrent::blockingMap(std::begin(_persistedDevices),std::end(_persistedDevices),[](Device *device)->void{device->checkAvailability();});
          }
          

          or using C++17:

          std::for_each(std::execution::par,std::begin(_persistedDevices),std::end(_persistedDevices),[](Device *device)->void{device->checkAvailability();});
          }
          
          D Offline
          D Offline
          Daniel Williams
          wrote on last edited by Daniel Williams
          #4

          @JonB Inside my iterator loop, I tried to use the waitForFishished() method, but the object browser in Qt creator didn't show the method:

              QVectorIterator<QFuture<void>> watcherIter(watchers);
              while (watcherIter.hasNext()) {
                watcherIter.next().??   //I could not get the object to show waitForFinished() as a method of the object.
              }
          
          1 Reply Last reply
          0
          • VRoninV VRonin

            @Daniel-Williams said in QTConcurrent returns QFuture but the QFuture object has no WaitForFinished method. How do I wait for the threads to finish:

            However, the QFuture objects returned from QtConcurrent don't have the WaitForFinished method.

            They do: http://doc.qt.io/qt-5/qfuture.html#waitForFinished

            The usual method do do what you are trying to do is to use blockingMap but that only supports containers having stl iterators (begin()/end()) and not java style iterators. If _persistedDevices supports std::begin/std::end then you can use:

            void ConfiguredDevices::updateConfiguredDevicesState() {
            QtConcurrent::blockingMap(std::begin(_persistedDevices),std::end(_persistedDevices),[](Device *device)->void{device->checkAvailability();});
            }
            

            or using C++17:

            std::for_each(std::execution::par,std::begin(_persistedDevices),std::end(_persistedDevices),[](Device *device)->void{device->checkAvailability();});
            }
            
            D Offline
            D Offline
            Daniel Williams
            wrote on last edited by
            #5

            @VRonin The blockingMap worked. thank you.

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

              I wanted to try out a lambda so I worked this up:

                  QVector<QString*> strings;
              
                  strings << new QString("one");
                  strings << new QString("two");
                  strings << new QString("three");
              
                  QVector<QFuture<void>> watchers;
              
                  for(auto string: strings){
                      qInfo() << *string << string;
                      watchers.append(QtConcurrent::run([string]() mutable {
                          //qInfo() << string;
                          qInfo() << *string << string;
                          *string += '&';
                      }));
                  }
              
                  for(auto watcher: watchers){
                      watcher.waitForFinished();
                  }
              
                  for(auto string: strings){
                      qInfo() << *string;
                      delete string;
                  }
              

              I don't know if this helps.

              C++ is a perfectly valid school of magic.

              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