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. executing query after cloned connection is used in another thread
Forum Update on Monday, May 27th 2025

executing query after cloned connection is used in another thread

Scheduled Pinned Locked Moved Unsolved General and Desktop
26 Posts 3 Posters 3.4k 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
    SGaist
    Lifetime Qt Champion
    wrote on 21 Aug 2019, 21:10 last edited by
    #11

    Indeed, let the database do that kind of stuff since it's made for that.

    Interested in AI ? www.idiap.ch
    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

    U 1 Reply Last reply 21 Aug 2019, 21:32
    0
    • S SGaist
      21 Aug 2019, 21:10

      Indeed, let the database do that kind of stuff since it's made for that.

      U Offline
      U Offline
      user4592357
      wrote on 21 Aug 2019, 21:32 last edited by
      #12

      @sgaist
      okay. and one thing i don't get is, the function that does the updating is called from a menu (action). now when the function is executed is executed in another thread I'd expect the menu to close, by it is not.

      here is another thing. the gui action calls a function, and in this function i instruct the thread to call the internal update function. should i do this? or call the first function initiated by the gui action from the new thread?

      S 1 Reply Last reply 23 Aug 2019, 20:32
      0
      • U Offline
        U Offline
        user4592357
        wrote on 22 Aug 2019, 08:46 last edited by user4592357
        #13

        okay so o tried to call qApp->processEvents() in the loop that updates the db. and i got rid of the thread. what about this solution?

        for (auto row : rows)
        {
        	// update the db for the table row
        	// ...
        
        	// process pending events
        	QCoreApplication::processEvents();
        }
        
        1 Reply Last reply
        0
        • U user4592357
          21 Aug 2019, 21:32

          @sgaist
          okay. and one thing i don't get is, the function that does the updating is called from a menu (action). now when the function is executed is executed in another thread I'd expect the menu to close, by it is not.

          here is another thing. the gui action calls a function, and in this function i instruct the thread to call the internal update function. should i do this? or call the first function initiated by the gui action from the new thread?

          S Offline
          S Offline
          SGaist
          Lifetime Qt Champion
          wrote on 23 Aug 2019, 20:32 last edited by
          #14

          @user4592357 said in executing query after cloned connection is used in another thread:

          @sgaist
          okay. and one thing i don't get is, the function that does the updating is called from a menu (action). now when the function is executed is executed in another thread I'd expect the menu to close, by it is not.

          here is another thing. the gui action calls a function, and in this function i instruct the thread to call the internal update function. should i do this? or call the first function initiated by the gui action from the new thread?

          Since I don't know how you implemented the thread more the menu setup, I can't comment on that.

          Interested in AI ? www.idiap.ch
          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

          U 1 Reply Last reply 23 Aug 2019, 20:36
          0
          • S SGaist
            23 Aug 2019, 20:32

            @user4592357 said in executing query after cloned connection is used in another thread:

            @sgaist
            okay. and one thing i don't get is, the function that does the updating is called from a menu (action). now when the function is executed is executed in another thread I'd expect the menu to close, by it is not.

            here is another thing. the gui action calls a function, and in this function i instruct the thread to call the internal update function. should i do this? or call the first function initiated by the gui action from the new thread?

            Since I don't know how you implemented the thread more the menu setup, I can't comment on that.

            U Offline
            U Offline
            user4592357
            wrote on 23 Aug 2019, 20:36 last edited by
            #15

            @sgaist
            okay and what about the process events solution?

            1 Reply Last reply
            0
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 23 Aug 2019, 20:53 last edited by
              #16

              Using processEvents is a last resort mesure that should be avoided.

              Interested in AI ? www.idiap.ch
              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

              U 1 Reply Last reply 23 Aug 2019, 21:02
              0
              • S SGaist
                23 Aug 2019, 20:53

                Using processEvents is a last resort mesure that should be avoided.

                U Offline
                U Offline
                user4592357
                wrote on 23 Aug 2019, 21:02 last edited by user4592357
                #17

                @sgaist
                okay so it means i need to go back to my thread implementation
                here's what i have

                bool doWork(const QString &newVal)
                {
                     for (each of selected table rows)
                     {
                          if (!table->updateRow(row, newVal))
                              return false;
                          // QCoreApplication::processEvents();
                     }
                    return true;
                }
                bool Table::updateRow(int row, const QString &newVal)
                {
                     m_thread.execute(updateQuery, row, newVal);
                     //...
                }
                

                when the processEvents is commented, the gui freezes, since the call to updateRow is executed in gui thread.
                what should i do? put the for loop of doWork() in the thread? (the table is generic and in my case i need to update the database but another table might do something else where multithreaded update is not needed... although it won't hurt maybe)

                1 Reply Last reply
                0
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 23 Aug 2019, 21:15 last edited by
                  #18

                  How proficient are you in the threading field ?

                  Because from the looks of it, you are directly calling methods on your thread class and expecting them to actually run in that other thread. It's not how it works.

                  Interested in AI ? www.idiap.ch
                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                  U 1 Reply Last reply 24 Aug 2019, 04:50
                  0
                  • S SGaist
                    23 Aug 2019, 21:15

                    How proficient are you in the threading field ?

                    Because from the looks of it, you are directly calling methods on your thread class and expecting them to actually run in that other thread. It's not how it works.

                    U Offline
                    U Offline
                    user4592357
                    wrote on 24 Aug 2019, 04:50 last edited by user4592357
                    #19

                    @sgaist
                    sorry for no context. i create the database and then use slots to execute the queries (because i want to execute the queries on some event, which is when the user decided to modify the data in my table widget).
                    roughly speaking, this is my implementation:

                    #pragma once
                    
                    #include <QThread>
                    #include <QDebug>
                    #include <QtSql/QSqlError>
                    #include <QtSql/QSqlDatabase>
                    #include <QtSql/QSqlQuery>
                    
                    class queryExecutor : public QObject
                    {
                    	Q_OBJECT
                    public:
                    	explicit queryExecutor(QObject *parent = nullptr) noexcept;
                    
                    	void setDatabase(const QString &sDbPath);
                    
                    public slots:
                    	void execute(const QString &query, const QHash<QString, QString> &mapBoundVals);
                    
                    signals:
                    	void finished(bool success, const QList<QSqlRecord> &records);
                    
                    private:
                    	QSqlDatabase m_db;
                    };
                    
                    class QueryThread : public QThread
                    {
                    	Q_OBJECT
                    public:
                    	explicit QueryThread(const QString &sDbPath) noexcept;
                    
                    protected:
                    	void run() override;
                    
                    signals:
                    	void queryFinished(bool success, const QList<QSqlRecord> &records);
                    
                    public slots:
                    	void execute(const QString &query, const QHash<QString, QString> &mapBoundVals);
                    
                    private:
                    	queryExecutor m_queryExecutor;
                    	QString m_sDbPath;
                    };
                    
                    queryExecutor::queryExecutor(QObject *parent /* = nullptr */) noexcept
                    {
                    }
                    
                    void queryExecutor::setDatabase(const QString &sDbPath)
                    {
                    	// create a thread-specific connection
                    	m_db = QSqlDatabase::addDatabase("QSQLITE", QString("%1_%2")
                    		.arg(sDbPath)
                    		.arg(QString::number((quint64)QThread::currentThreadId(), 16)));
                    
                    	qDebug() << "conn name" << QString("%1_%2")
                    		.arg(sDbPath)
                    		.arg(QString::number((quint64)QThread::currentThreadId(), 16));
                    
                    	m_db.setDatabaseName(sDbPath);
                    
                    	if (!m_db.open())
                    	{
                    		qDebug() << "db not open:" << m_db.lastError().text();
                    	}
                    }
                    
                    void queryExecutor::execute(const QString &query, const QHash<QString, QString> &mapBoundVals)
                    {
                    	QList<QSqlRecord> records;
                    	QSqlQuery sqlQuery(m_db);
                    	sqlQuery.prepare(query);
                    
                    	for (const auto &sPlaceholder : mapBoundVals.keys())
                    	{
                    		auto bound = mapBoundVals[sPlaceholder];
                    		sqlQuery.bindValue(sPlaceholder, bound);
                    	}
                    
                    	if (!sqlQuery.exec())
                    	{
                    		qDebug() << "query failed:" << sqlQuery.lastError().text();
                    		emit finished(false, records);
                    		return;
                    	}
                    
                    	while (sqlQuery.next())
                    		records.push_back(sqlQuery.record());
                    
                    	emit finished(true, records);
                    }
                    
                    QueryThread::QueryThread(const QString &sDbPath) noexcept
                    	: m_sDbPath(sDbPath)
                    {
                    }
                    
                    void QueryThread::execute(const QString &query, const QHash<QString, QString> &mapBoundVals)
                    {
                    	// forward the execution to the worker
                    	m_queryExecutor.execute(query, mapBoundVals);
                    }
                    
                    void QueryThread::run()
                    {
                    	qDebug() << "started thread" << QThread::currentThreadId();
                    
                    	m_queryExecutor.setDatabase(m_sDbPath);
                    
                    	// forward final signal
                    	connect(&m_queryExecutor, &queryExecutor::finished, this, &QueryThread::queryFinished);
                    
                    	exec();
                    }
                    
                    1 Reply Last reply
                    0
                    • Christian EhrlicherC Offline
                      Christian EhrlicherC Offline
                      Christian Ehrlicher
                      Lifetime Qt Champion
                      wrote on 24 Aug 2019, 13:40 last edited by
                      #20

                      Your function queryExecutor::execute() is not run in your thread since the slot from where it's called is a function from an object which lives in the main thread. I would suggest reading the QThread documentation on how to properly use Signals/Slots with QThread: https://doc.qt.io/qt-5/threads-qobject.html

                      Qt Online Installer direct download: https://download.qt.io/official_releases/online_installers/
                      Visit the Qt Academy at https://academy.qt.io/catalog

                      U 1 Reply Last reply 24 Aug 2019, 14:45
                      1
                      • Christian EhrlicherC Christian Ehrlicher
                        24 Aug 2019, 13:40

                        Your function queryExecutor::execute() is not run in your thread since the slot from where it's called is a function from an object which lives in the main thread. I would suggest reading the QThread documentation on how to properly use Signals/Slots with QThread: https://doc.qt.io/qt-5/threads-qobject.html

                        U Offline
                        U Offline
                        user4592357
                        wrote on 24 Aug 2019, 14:45 last edited by user4592357
                        #21

                        @christian-ehrlicher
                        yeah that's right. query executor should execute the query since it is in the new thread, so the code should be like this:

                        void QueryThread::execute(const QString &query, const QHash<QString, QString> &mapBoundVals)
                        {
                        	// forward the execution to the worker
                        	emit executefwd(query, mapBoundVals);
                        }
                        
                        void QueryThread::run()
                        {
                        	qDebug() << "started thread" << QThread::currentThreadId();
                        
                        	m_queryExecutor.setDatabase(m_sDbPath);
                        
                                connect( this, SIGNAL( executefwd( const QString&, const QHash<QString, QString> & ) ),
                                     m_queryExecutor, SLOT( execute( const QString&, const QHash<QString, QString> & ) ) );
                        
                        	// forward final signal
                        	connect(&m_queryExecutor, &queryExecutor::finished, this, &QueryThread::queryFinished);
                        
                        	exec();
                        }
                        1 Reply Last reply
                        0
                        • S Offline
                          S Offline
                          SGaist
                          Lifetime Qt Champion
                          wrote on 24 Aug 2019, 15:42 last edited by
                          #22

                          Your executor still lives in the main thread as it is created at your custom thread subclass creation time.

                          Interested in AI ? www.idiap.ch
                          Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                          U 1 Reply Last reply 24 Aug 2019, 15:58
                          1
                          • S SGaist
                            24 Aug 2019, 15:42

                            Your executor still lives in the main thread as it is created at your custom thread subclass creation time.

                            U Offline
                            U Offline
                            user4592357
                            wrote on 24 Aug 2019, 15:58 last edited by
                            #23

                            @sgaist
                            oh okay, so it should be newed in QueryThread::run()

                            1 Reply Last reply
                            0
                            • S Offline
                              S Offline
                              SGaist
                              Lifetime Qt Champion
                              wrote on 25 Aug 2019, 19:12 last edited by
                              #24

                              It can be on the stack. It really depends on how you want to implement that stuff. You seem to be mixing the worker object approach with the subclass QThread approach.

                              Interested in AI ? www.idiap.ch
                              Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                              U 1 Reply Last reply 26 Aug 2019, 05:46
                              0
                              • S SGaist
                                25 Aug 2019, 19:12

                                It can be on the stack. It really depends on how you want to implement that stuff. You seem to be mixing the worker object approach with the subclass QThread approach.

                                U Offline
                                U Offline
                                user4592357
                                wrote on 26 Aug 2019, 05:46 last edited by
                                #25

                                @sgaist
                                i followed this example for my implementation: https://www.linuxjournal.com/article/9602
                                but anyways i think thread is still not much helpful because my for loop still executes in main thread. am i right?

                                bool doWork(const QString &newVal)
                                {
                                     for (each of selected table rows)
                                     {
                                          if (!table->updateRow(row, newVal))
                                              return false;
                                     }
                                    return true;
                                }
                                
                                bool Table::updateRow(int row, const QString &newVal)
                                {
                                     //update in another thread
                                }
                                
                                1 Reply Last reply
                                0
                                • S Offline
                                  S Offline
                                  SGaist
                                  Lifetime Qt Champion
                                  wrote on 1 Feb 2020, 22:28 last edited by
                                  #26

                                  As already said, you are mixing two different technique the wrong way.

                                  If you subclass QThread and re-implement run, then what is executed in run happens in the thread managed by QThread.

                                  However, you created an instance of your worker object in the original thread since it's part of your QThread subclass and thus the slot will be executed in the original thread.

                                  Interested in AI ? www.idiap.ch
                                  Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                  1 Reply Last reply
                                  1

                                  • Login

                                  • Login or register to search.
                                  • First post
                                    Last post
                                  0
                                  • Categories
                                  • Recent
                                  • Tags
                                  • Popular
                                  • Users
                                  • Groups
                                  • Search
                                  • Get Qt Extensions
                                  • Unsolved