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 and recursion
Qt 6.11 is out! See what's new in the release blog

QtConcurrent and recursion

Scheduled Pinned Locked Moved Solved General and Desktop
2 Posts 1 Posters 900 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.
  • S Offline
    S Offline
    Sanych.by
    wrote on last edited by Sanych.by
    #1

    Good day. I tried execute some long operation which use recursion with QtConcurrent::run. But signal finished() of QFutureWatcher not emitted for all calls. Here code:
    MainWIndow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    #include <QThreadPool>
    
    namespace Ui {
    class MainWindow;
    }
    
    class WatcherHandler: public QObject
    {
        Q_OBJECT
    public slots:
        void    watcherFinished();
    };
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = nullptr);
        ~MainWindow();
    
    private slots:
        void on_pushButton_clicked();
        QString recurse(int level, int count = 0);
    private:
        QThreadPool *pool;
        int MaxLevel;
        Ui::MainWindow *ui;
        WatcherHandler *h;
    };
    #endif // MAINWINDOW_H
    
    

    MainWindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include <QtConcurrent>
    #include <QDebug>
    #include <QThread>
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        pool = nullptr;
        ui->setupUi(this);
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
        if(pool)
            delete pool;
    }
    
    void MainWindow::on_pushButton_clicked()
    {
        QThread *thrd = new QThread;
        h = new WatcherHandler;
        h->moveToThread(thrd);
        connect(qApp, &QApplication::aboutToQuit,
                thrd, &QThread::deleteLater);
        thrd->start();
        pool = new QThreadPool;
        MaxLevel = 3;
        //QtConcurrent::run(pool, this, &MainWindow::recurse,0,0);
        recurse(0);
    }
    
    QString MainWindow::recurse(int level, int count)
    {
        qDebug() << "Thread : " << QThread::currentThread() << " : " << thread();
        qDebug() << "Start recurse level " << level << count;
        unsigned long worktime = 1000/(level+1)-level;
        QThread::currentThread()->msleep(worktime);
        if(level < MaxLevel)
            for(int i = 0; i <= level; i++)
            {
                QFutureWatcher<QString> *watcher = new QFutureWatcher<QString>;
                connect(watcher, &QFutureWatcher<QString>::finished,
                        h, &WatcherHandler::watcherFinished,
                        Qt::QueuedConnection);
                QFuture<QString> f =
                        QtConcurrent::run(pool, this, &MainWindow::recurse,
                                                       level+1, i);
                watcher->setFuture(f);
    
            }
        QThread::currentThread()->msleep(worktime);
        qDebug() << "Finished recurce level" << level << count;
        return QString("level %1 count %2").arg(level).arg(count);
    }
    
    void WatcherHandler::watcherFinished()
    {
        QFutureWatcher<QString> *watcher = static_cast<QFutureWatcher<QString> *>
                (QObject::sender());
        qDebug() << "Thread : " << QThread::currentThread();
        qDebug() << "SIGNAL FINISHED EMITED FOR" << watcher->result();
    }
    

    And debug log:
    Thread : QThread(0x3da9c0) : QThread(0x3da9c0)
    Start recurse level 0 0
    Thread : QThread(0x42b430, name = "Thread (pooled)") : QThread(0x3da9c0)
    Start recurse level 1 0
    Thread : QThread(0x463950, name = "Thread (pooled)") : QThread(0x3da9c0)
    Thread : QThread(0x463b80, name = "Thread (pooled)") : QThread(0x3da9c0)
    Start recurse level 2 0
    Start recurse level 2 1
    Thread : QThread(0x463db0, name = "Thread (pooled)") : QThread(0x3da9c0)
    Start recurse level 3 0
    Finished recurce level 1 0
    Thread : QThread(0x42b430, name = "Thread (pooled)") : QThread(0x3da9c0)
    Start recurse level 3 0
    Finished recurce level 0 0
    Thread : QThread(0x466890)
    SIGNAL FINISHED EMITED FOR "level 1 count 0"
    Finished recurce level 2 0
    Finished recurce level 2 1
    Thread : QThread(0x463950, name = "Thread (pooled)") : QThread(0x3da9c0)
    Thread : QThread(0x463b80, name = "Thread (pooled)") : QThread(0x3da9c0)
    Start recurse level 3 1
    Start recurse level 3 1
    Finished recurce level 3 0
    Thread : QThread(0x463db0, name = "Thread (pooled)") : QThread(0x3da9c0)
    Start recurse level 3 2
    Finished recurce level 3 0
    Thread : QThread(0x42b430, name = "Thread (pooled)") : QThread(0x3da9c0)
    Start recurse level 3 2
    Finished recurce level 3 1
    Finished recurce level 3 1
    Finished recurce level 3 2
    Finished recurce level 3 2

    Where is my fall?
    P.S. I add qDebug for connect call, always return true. Seems like only first recursion deep emitted. But in real example i got also signals for second level (maybe it depends on time of operation). And for last 3-5 calls of second level (all calls second level was about 180-190) I never got finished signal.

    1 Reply Last reply
    0
    • S Offline
      S Offline
      Sanych.by
      wrote on last edited by
      #2

      Ok. I I made it work after making QThread object a member and moving each QFutureWatcher object to it. I guess something wrong was in creating watcher in thread of QtConcurrent::run and when one call of recurse with QtConcurrent::run is finished, all watchers created in it, even dynamically and without a parent, were lost, or their connections were lost.
      I don't understand why it is so but it works. If someone can explain me this situation and why it works this way, i would be very thankful for explainations, so i would use CONNECT mechanism right in future.

      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