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. QSqlDatabase + multiple threads
QtWS25 Last Chance

QSqlDatabase + multiple threads

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 3 Posters 7.7k 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.
  • D Offline
    D Offline
    drbroly
    wrote on last edited by drbroly
    #1

    Hi, I'm trying to allow mutiple threads to perform reads from my database. From what I understand from the documentation (http://doc.qt.io/qt-5/qsqldatabase.html), this should be possible as long as each thread creates, uses and maintains it's own connection. Here, I have a launch 3 threads, and on a timer they will access each database.

    DataBaseConnector.h

    #include <QObject>
    #include <QtSQL>
    
    class DatabaseConnector : public QObject
    {
    	Q_OBJECT
    
    public:
    	DatabaseConnector(int id);
    	~DatabaseConnector();
    
    private:
    	int myID;
    	QSqlDatabase _db;
    	QSqlQuery query;
    	QTimer *timer;
    	QString conName;
    
    public slots:
    	void run();
    	void tick();
    
    signals:
    	void sendText(QString text);
    };
    

    .cpp

    #include "DatabaseConnector.h"
    
    DatabaseConnector::DatabaseConnector(int id)
    {
    	myID = id;
    }
    
    DatabaseConnector::~DatabaseConnector()
    {
     //TO-DO CLEANUP
    }
    
    void DatabaseConnector::run()
    {
    	conName = QStringLiteral("_conSldb_") + QString::number(myID);
    	//Create a connection with a unique name
    	_db = QSqlDatabase::addDatabase("QMYSQL", conName);
    	_db.setHostName("localhost"); //Go to local host
    	_db.setDatabaseName("world"); //Open the "world" schema
    	_db.setUserName("xxxxx");
    	_db.setPassword("xxxxx");
    	bool ok = _db.open();
    
    	if (ok)
    	{
    		timer = new QTimer(this);
    		connect(timer, SIGNAL(timeout()), this, SLOT(tick()));
    		timer->start(1000);
    	}
    	else
    	{
    		qDebug() << "failed to open db at thread_id: " + myID;
    	}
    }
    
    void DatabaseConnector::tick()
    {
    	QSqlQuery query(QSqlDatabase::database(conName));
    		query.exec("SELECT Language, CountryCode FROM countrylanguage WHERE Language = 'Dutch'");
    		while (query.next())
    		{
    			QString name = query.value(1).toString();
    			//TODO - emit to gui
    			//emit sendText(name);
    		}
    }
    

    main

    #include <QtSQL>
    #include "DatabaseConnector.h"
    #include <qtconcurrentrun.h>
    
    
    int main(int argc, char *argv[])
    {
    	QCoreApplication a(argc, argv);
    
    	QThread *thread1 = new QThread;
    	QThread *thread2 = new QThread;
    	QThread *thread3 = new QThread;
    
    	DatabaseConnector* db1 = new DatabaseConnector(1);
    	DatabaseConnector* db2 = new DatabaseConnector(2);
    	DatabaseConnector* db3 = new DatabaseConnector(3);
    
    	db1->moveToThread(thread1);
    	QObject::connect(thread1, SIGNAL(started()), db1, SLOT(run()));
    
    	db2->moveToThread(thread2);
    	QObject::connect(thread2, SIGNAL(started()), db2, SLOT(run()));
    
    	db3->moveToThread(thread3);
    	QObject::connect(thread3, SIGNAL(started()), db3, SLOT(run()));
    
    	thread1->start();
    	thread2->start();
    	thread3->start();
    
    	return a.exec();
    }
    

    This setup works with one thread, but with 2+ I get:

    "QObject::moveToThread: Current thread (0xb9b648) is not the object's thread (0xb9c0b0).
    Cannot move to target thread (0xb8f298)".

    This typically happens around the "bool ok = _db.open();" line within the run(). Cleanup issues aside, I cannot see anything wrong with the thread setup in the main.

    Could anyone please offer any insight into my issues?

    UPDATE:

    lastError() returns "Unknown MySQL server host 'localhost'". One thread has no problem finding it, the others fail to know it exists. Yet the issue that prints is "QObject::moveToThread: Current thread (0xb9b648) is not the object's thread (0xb9c0b0)..."

    VRoninV 1 Reply Last reply
    0
    • D drbroly

      Hi, I'm trying to allow mutiple threads to perform reads from my database. From what I understand from the documentation (http://doc.qt.io/qt-5/qsqldatabase.html), this should be possible as long as each thread creates, uses and maintains it's own connection. Here, I have a launch 3 threads, and on a timer they will access each database.

      DataBaseConnector.h

      #include <QObject>
      #include <QtSQL>
      
      class DatabaseConnector : public QObject
      {
      	Q_OBJECT
      
      public:
      	DatabaseConnector(int id);
      	~DatabaseConnector();
      
      private:
      	int myID;
      	QSqlDatabase _db;
      	QSqlQuery query;
      	QTimer *timer;
      	QString conName;
      
      public slots:
      	void run();
      	void tick();
      
      signals:
      	void sendText(QString text);
      };
      

      .cpp

      #include "DatabaseConnector.h"
      
      DatabaseConnector::DatabaseConnector(int id)
      {
      	myID = id;
      }
      
      DatabaseConnector::~DatabaseConnector()
      {
       //TO-DO CLEANUP
      }
      
      void DatabaseConnector::run()
      {
      	conName = QStringLiteral("_conSldb_") + QString::number(myID);
      	//Create a connection with a unique name
      	_db = QSqlDatabase::addDatabase("QMYSQL", conName);
      	_db.setHostName("localhost"); //Go to local host
      	_db.setDatabaseName("world"); //Open the "world" schema
      	_db.setUserName("xxxxx");
      	_db.setPassword("xxxxx");
      	bool ok = _db.open();
      
      	if (ok)
      	{
      		timer = new QTimer(this);
      		connect(timer, SIGNAL(timeout()), this, SLOT(tick()));
      		timer->start(1000);
      	}
      	else
      	{
      		qDebug() << "failed to open db at thread_id: " + myID;
      	}
      }
      
      void DatabaseConnector::tick()
      {
      	QSqlQuery query(QSqlDatabase::database(conName));
      		query.exec("SELECT Language, CountryCode FROM countrylanguage WHERE Language = 'Dutch'");
      		while (query.next())
      		{
      			QString name = query.value(1).toString();
      			//TODO - emit to gui
      			//emit sendText(name);
      		}
      }
      

      main

      #include <QtSQL>
      #include "DatabaseConnector.h"
      #include <qtconcurrentrun.h>
      
      
      int main(int argc, char *argv[])
      {
      	QCoreApplication a(argc, argv);
      
      	QThread *thread1 = new QThread;
      	QThread *thread2 = new QThread;
      	QThread *thread3 = new QThread;
      
      	DatabaseConnector* db1 = new DatabaseConnector(1);
      	DatabaseConnector* db2 = new DatabaseConnector(2);
      	DatabaseConnector* db3 = new DatabaseConnector(3);
      
      	db1->moveToThread(thread1);
      	QObject::connect(thread1, SIGNAL(started()), db1, SLOT(run()));
      
      	db2->moveToThread(thread2);
      	QObject::connect(thread2, SIGNAL(started()), db2, SLOT(run()));
      
      	db3->moveToThread(thread3);
      	QObject::connect(thread3, SIGNAL(started()), db3, SLOT(run()));
      
      	thread1->start();
      	thread2->start();
      	thread3->start();
      
      	return a.exec();
      }
      

      This setup works with one thread, but with 2+ I get:

      "QObject::moveToThread: Current thread (0xb9b648) is not the object's thread (0xb9c0b0).
      Cannot move to target thread (0xb8f298)".

      This typically happens around the "bool ok = _db.open();" line within the run(). Cleanup issues aside, I cannot see anything wrong with the thread setup in the main.

      Could anyone please offer any insight into my issues?

      UPDATE:

      lastError() returns "Unknown MySQL server host 'localhost'". One thread has no problem finding it, the others fail to know it exists. Yet the issue that prints is "QObject::moveToThread: Current thread (0xb9b648) is not the object's thread (0xb9c0b0)..."

      VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #2

      conName = "_conSldb_" + myID; does not do what you think it does. use conName = QStringLiteral("_conSldb_") + QString::number(myID);

      "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
      ~Napoleon Bonaparte

      On a crusade to banish setIndexWidget() from the holy land of Qt

      D 1 Reply Last reply
      0
      • VRoninV VRonin

        conName = "_conSldb_" + myID; does not do what you think it does. use conName = QStringLiteral("_conSldb_") + QString::number(myID);

        D Offline
        D Offline
        drbroly
        wrote on last edited by
        #3

        @VRonin Thanks for the suggestion, it certainly ensures the parameter is formatted. I've amended the line but there's no change to functionality.

        1 Reply Last reply
        0
        • VRoninV Offline
          VRoninV Offline
          VRonin
          wrote on last edited by
          #4

          before bool ok = _db.open(); could you check what _db.isOpen(); returns?

          "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
          ~Napoleon Bonaparte

          On a crusade to banish setIndexWidget() from the holy land of Qt

          D 1 Reply Last reply
          0
          • VRoninV VRonin

            before bool ok = _db.open(); could you check what _db.isOpen(); returns?

            D Offline
            D Offline
            drbroly
            wrote on last edited by
            #5

            @VRonin said in QSqlDatabase + multiple threads:

            Always false, maybe because I haven't called open() yet.

            If I call after, it returns true if is also "ok" is true. If ok is false, it also returns false.

            1 Reply Last reply
            0
            • SGaistS Offline
              SGaistS Offline
              SGaist
              Lifetime Qt Champion
              wrote on last edited by
              #6

              Hi,

              Why are you keeping member variables fro query and _db ?

              You don't need them.

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

              D 1 Reply Last reply
              1
              • SGaistS SGaist

                Hi,

                Why are you keeping member variables fro query and _db ?

                You don't need them.

                D Offline
                D Offline
                drbroly
                wrote on last edited by drbroly
                #7

                @SGaist

                Hello. You're right. I'm still getting accustomed to the system and figuring this out.

                Small update: lastError() returns "Unknown MySQL server host 'localhost'". One thread has no problem finding it, the others fail to know it exists. Yet the issue that prints is "QObject::moveToThread: Current thread (0xb9b648) is not the object's thread (0xb9c0b0)..."

                1 Reply Last reply
                0
                • SGaistS Offline
                  SGaistS Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  One thing to take into account is that everything that is happening at construction time happens in the main thread thus the object created there are created in the main thread.. When moving your worker to another thread only objects which have the worker as parent will get moved with it. Then what you create in your DatabaseConnector run function will have affinity with the thread where you moved the worker to.

                  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
                  0

                  • Login

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