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
Forum Updated to NodeBB v4.3 + New Features

QtConcurrent and recursion

Scheduled Pinned Locked Moved Solved General and Desktop
2 Posts 1 Posters 442 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