Need help with multithreading



  • Hi. I have a function which I want to call with few instances in several threads. I suppose to use something like that:

    void MainWindow::btn_clicked () {
        for (int i = 0; i < 10; ++i) {
            // different parts computing in different threads
            Function(a,b); // thread 1
            Function(b,c); // thread 2
    
            // after tasks in all threads are done
            UpdateMap(); // update QGrapchicScene
            sleep(delay); // pause
        }
    }
    

    But during cycle is proceeding GUI should not be frozen.
    So, what is the best practice to do that? QThreads or QConcurrent or something else?


  • Lifetime Qt Champion

    Hi,

    QtConcurrent sounds like a good choice. However, the UpdateMap function should be connected to a QFutureWatcher to only run once all operations are done.

    Why the call to sleep ?



  • I need pause just to see updated map.
    Well, I'm trying to find out how to use QtConcurrent right now, but there is no significant success. I try:

    future1 = new QFuture<void>;
    watcher1 = new QFutureWatcher<void>;
    future2 = new QFuture<void>;
    watcher2 = new QFutureWatcher<void>;
    connect(watcher1, SIGNAL(finished()),
                   this, SLOT(S()));
    connect(watcher2, SIGNAL(finished()),
                   this, SLOT(S()));
    
    size_t s = fieldSizeI / 2;
    for (size_t i = 0; i < 10; ++i) {
        *future1 = QtConcurrent::run(field, &Field::PerformIteration, 0, s);
        *future2 = QtConcurrent::run( field, &Field::PerformIteration, s, 2*s);
    
        watcher1->setFuture(*future1);
        watcher2->setFuture(*future2);
    }
    
    void MainWindow::S() {
        ++workCounter;
        if (workCounter == 2) {
            field->AdoptNewState();
            UpdateMap();
            workCounter = 0;
        }
    }
    

    It seems I'am doing it absolutely wrong. And I can't find an appropriate example.


  • Lifetime Qt Champion

    QFutureWatcher *watcher1 = new QFutureWatcher<void>;
    QFutureWatcher *watcher2 = new QFutureWatcher<void>;
    connect(watcher1, SIGNAL(finished()),
                   this, SLOT(S()));
    connect(watcher2, SIGNAL(finished()),
                   this, SLOT(S()));
     
    size_t s = fieldSizeI / 2;
    
        QFuture<void> future1 = QtConcurrent::run(field, &Field::PerformIteration, 0, s);
    QFuture<void> future2 = QtConcurrent::run( field, &Field::PerformIteration, s, 2*s);
     
        watcher1->setFuture(future1);
        watcher2->setFuture(future2);
    }
    


  • Thanks. I used your code to construct the thing below. It looks not so hot but work just how I need.

    // call this function to start
    void MainWindow::on_btn_iter_clicked()
    {
        maxIter = 5;
        s = fieldSizeI / threadsAmount;
        NewIteration();
    }
    
    void MainWindow::NewIteration() {
        std::vector<QFutureWatcher<void> *> watchers (threadsAmount);
        for (size_t i = 0; i < threadsAmount; ++i) {
            watchers[i] = new QFutureWatcher<void>;
            connect (watchers[i], SIGNAL (finished()), this, SLOT (S()));
        }
        typedef std::vector<QFuture<void> > futures (threadsAmount);
        for (size_t i = 0; i < threadsAmount; ++i) {
            futures[i] = QtConcurrent::run(field, &CA_Field::PerformIteration,
                                           i*s, (i+1)*s );
            watchers[i]->setFuture(futures[i]);
        }
    }
    
    void MainWindow::S() {
        ++workCounter;
        if (workCounter == threadsAmount) {
            field->AdoptNewState();
            workCounter = 0;
            (--maxIter != 0) ? NewIteration() : UpdateHexMap();
        }
    }
    

Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.