Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

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



  • 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?



  • @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"?



  • @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();});
    }
    


  • @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.
        }
    


  • @VRonin The blockingMap worked. thank you.



  • 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.


Log in to reply