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

QSqlDatabase + multiple threads

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 3 Posters 7.8k 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 16 Mar 2017, 12:14 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)..."

    V 1 Reply Last reply 16 Mar 2017, 12:24
    0
    • D drbroly
      16 Mar 2017, 12:14

      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)..."

      V Offline
      V Offline
      VRonin
      wrote on 16 Mar 2017, 12:24 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 16 Mar 2017, 12:49
      0
      • V VRonin
        16 Mar 2017, 12:24

        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 16 Mar 2017, 12:49 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
        • V Offline
          V Offline
          VRonin
          wrote on 16 Mar 2017, 12:52 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 16 Mar 2017, 13:03
          0
          • V VRonin
            16 Mar 2017, 12:52

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

            D Offline
            D Offline
            drbroly
            wrote on 16 Mar 2017, 13:03 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
            • S Offline
              S Offline
              SGaist
              Lifetime Qt Champion
              wrote on 16 Mar 2017, 22:47 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 17 Mar 2017, 11:10
              1
              • S SGaist
                16 Mar 2017, 22:47

                Hi,

                Why are you keeping member variables fro query and _db ?

                You don't need them.

                D Offline
                D Offline
                drbroly
                wrote on 17 Mar 2017, 11:10 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
                • S Offline
                  S Offline
                  SGaist
                  Lifetime Qt Champion
                  wrote on 17 Mar 2017, 21:14 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

                  5/8

                  16 Mar 2017, 13:03

                  • Login

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