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

How to replace QThread with QtConcurrent



  • I have a SQL fetching class that connects to SQL and fetched the required data.

    I wanted to this in another thread so I did that with QThread. It is working as it should be.

    But now I want to replace it with QTConcurrent. The problem I face with QTconcureent is that I need a connect command that initializes the database before the thread uses to do SQL query.

    Here are my codes created is the public slot and qint64TotalSize is the public method of the SqlFetcher class.

    Controller::Controller(QObject *parent) : QObject(parent)
    {
        SqlFetcher* m_Fetcher = new SqlFetcher();
    
        qInfo() <<"Start"<< QThread::currentThread();
    
         QFutureWatcher<void> watcher;
         QFuture <void> future1 = QtConcurrent::run(m_Fetcher,&SqlFetcher::qint64TotalSize);
    
         watcher.setFuture(future1);
    
    
        //QThread* t1 = new QThread();
        //m_Fetcher->moveToThread(t1);
    
        //connect(t1, &QThread::started, m_Fetcher, &SqlFetcher::createDb);
        //connect(t1, &QThread::started, m_Fetcher, &SqlFetcher::qint64TotalSize);
        //t1->start();
    
    
        qInfo() <<"Finish"<< QThread::currentThread();
    
    }
    
    void SqlFetcher::qint64TotalSize()
    {
        qint64 l_result= 0;
        QSqlQuery l_query;
    
        if (m_sqldb.isValid())
        {
            m_sqldb.open();
    
            if ((m_sqldb.isOpen()))
            {
                l_query.prepare("SELECT COUNT(*) FROM table1");
                l_query.exec();
    
                if (l_query.next()) {
                    l_result= l_query.value(0).toInt();
                }
                m_sqldb.close();
            }
        }
    
        qInfo() << l_result << QThread::currentThread();
    }
    
    void SqlFetcher::createDb()
    {
        m_sqldb = QSqlDatabase::addDatabase("QSQLITE");
        m_sqldb.setDatabaseName("xyz.db");
         qInfo() << "createDB" << QThread::currentThread();
    }
    

    My current output is

    Start QThread(0x7feab4c0f060)
    Finish QThread(0x7feab4c0f060)
    0 QThread(0x7feab4d42070, name = "Thread (pooled)")
    

    Expected Output or Output with Qthread is

    Start QThread(0x7fe82140f060)
    Finish QThread(0x7fe82140f060)
    createDB QThread(0x7fe82155c840)
    151 QThread(0x7fe82155c840)
    

  • Lifetime Qt Champion

    From what you wrote, you didn't follow any of my advices.

    Again: Read the QSqlDatabase documentation, the QSqlDatabase::database method documentation and this QSqlQuery constructor documentation.

    Again: You have to create a separate named connection for each thread you are using to connect to your database.


  • Lifetime Qt Champion

    Hi,

    No, the connection to the database needs to be done within the thread. You can't re-use the same connection in several different threads. Create a new named connection each time your run your worker object.
    Also, don't keep a QSqlDatabase object as member variable. Read the QSqlDatabase documentation to see how to retrieve the correct connection when needed.



  • Thank You for the reply.

    I tried this by editing qint64TotalSize() to make sure connection is within the thread like

    void SqlFetcher::qint64TotalSize()
    {
        qint64 l_result= 0;
        QSqlQuery l_query;
    
        if (!m_sqldb.isValid())
        {
            createDb();
        }
    
        m_sqldb.open();
    
        if ((m_sqldb.isOpen()))
        {
            l_query.prepare("SELECT COUNT(*) FROM table1");
            l_query.exec();
    
            if (l_query.next()) {
                l_result= l_query.value(0).toInt();
            }
            m_sqldb.close();
        }
    
        qInfo() << l_result << QThread::currentThread();
    }
    

    but the output is

    Start QThread(0x7fec9cc0f060)
    Finish QThread(0x7fec9cc0f060)
    createDB QThread(0x7fec9f0a65d0, name = "Thread (pooled)")
    QSqlQuery::prepare: database not open
    0 QThread(0x7fec9f0a65d0, name = "Thread (pooled)")
    

  • Lifetime Qt Champion

    From what you wrote, you didn't follow any of my advices.

    Again: Read the QSqlDatabase documentation, the QSqlDatabase::database method documentation and this QSqlQuery constructor documentation.

    Again: You have to create a separate named connection for each thread you are using to connect to your database.



  • @Mandeep-Chaudhary As @SGaist has written, is not allowed to use a QSqlConnection() outside from the thread in which it has been created/initialized.
    If you want to do multithreading and don't want your application to crash, you have to follow this!

    Take a look at this post: https://forum.qt.io/post/533583, it is about SQLite Database, but it is easy to port to another kind of DB.



  • Thank You guys for the reply. I undesrtood what you guys are saying but as I am new to QT so keeps on getting confused.

    What you guys saying make sense with examples in mentioned threads I succeeded.

    Thank You !!!


Log in to reply