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

Need help on QtConcurrent usage.



  • Hi to all,
    I'm doing some heavy computing, like accessing a database, that blocks my UI. So, I'm implementing the QtConcurrent::run function to start some class methods. These methods retrieve data from database table to fill out a classic QComboBox. After the
    @ui->setupUi(this);@

    in my form ctor I'm running these commands:

    @
    QFuture<void> f1 = QtConcurrent::run(this, &frmPractices_CRUD::populateComboSubjects);
    QFuture<void> f2 = QtConcurrent::run(this, &frmPractices_CRUD::populateComboSellPoints);
    f1.waitForFinished();
    f2.waitForFinished();
    @

    and the code is compiled but I get a Visual C++ Runtime Library errors!
    Then I tried to debug the functions and maybe my debugging skill isn't so good yet. I get the program works without errors only making the following changes:

    @
    QFuture<void> f1 = QtConcurrent::run(this, &frmPractices_CRUD::populateComboSubjects);
    f1.waitForFinished();
    QFuture<void> f2 = QtConcurrent::run(this, &frmPractices_CRUD::populateComboSellPoints);
    f2.waitForFinished();
    @

    And I don't think that's the right way to use QtConcurrent, my populateComboABCD functions contain the same code:

    @
    ui->cboSubject->clear();

    QSqlDatabase db = QSqlDatabase::database();
    QString tSqlCommand =
        QString(
            "SELECT "
            "sog_id, "
            "concat_ws(' ', sog_cogn, sog_nome) AS names, "
            "concat_ws(' - ', sog_codf, sog_piva) AS fiscals "
            "FROM %1.subjects "
            "WHERE (sog_tipo = 1) OR (sog_tipo = 3) "
            "ORDER BY names"
        ).arg(MyQtUtility::instance()->schemaName());
    QSqlQuery tSqlQuery(db);
    if (tSqlQuery.exec&#40;tSqlCommand&#41;) {
        while (tSqlQuery.next()) {
            QString tmpCboText;
    
            tmpCboText += tSqlQuery.value(1).toString().simplified();
            if (!tSqlQuery.value(2).toString().simplified().isEmpty()) {
                tmpCboText += " / " + tSqlQuery.value(2).toString().simplified();
            }
    
            ui->cboSubject->addItem(tmpCboText.trimmed(), tSqlQuery.value(0).toInt());
        }
    }
    tSqlQuery.finish();
    

    @

    Thanks in advance,
    Danilo


  • Moderators

    @
    QFuture<void> f1 = QtConcurrent::run(this, &frmPractices_CRUD::populateComboSubjects);
    f1.waitForFinished();
    QFuture<void> f2 = QtConcurrent::run(this, &frmPractices_CRUD::populateComboSellPoints);
    f2.waitForFinished();
    @
    You're right. It's not good this way. This is a sequential code. It is the same as
    @
    populateComboSubjects();
    populateComboSellPoints();
    @
    The problem is not with QtConcurrent. It's with the populate* methods. They run in separate threads and you can access UI only in the main thread, so calls to ui->cboSubject->clear() and ui->cboSubject->addItem() are not allowed there.

    You can run your sql queries in the worker threads but you need to signal the main thread to do the UI update.



  • Thanks Chris, but commenting the ui->cboSubject calls I get the same errors. I noted that the debug mode is stopping on MyQtUtility::instance()->schemaName() (it's a singleton class) command whithout breakpoint!! I don't know how strange it is but seems a wrong behavior.



  • I googled a bit and got the perception that a QSqlDatabase can not be used within two threads.


  • Lifetime Qt Champion

    Hi,

    AFAIK, you need to at least create a different connection for each thread in order to access the database.



  • Thanks Sgaist, I'll investigate that and if the game is worth the candle.


Log in to reply