PDA

View Full Version : QSqlQuery and no response while exec()



jacek_
3rd November 2009, 14:34
Hello my friends. I am writing an application using MySQL database. The problem is, the database server is far, far away and it takes much time to get some results. Unfortunately, QSqlQuery.exec() causes application to freeze (no response) until I get response from the server. I am looking for easy and efficient way to stop these freezes or to inform users about ongoing process. Any suggestions?

spirit
3rd November 2009, 15:13
I'm afraid you should use thread, i.e. move all SQL-queryies in separate thread and establish communication between main thread and worker thread using signals/slots mechanism.

jacek_
3rd November 2009, 15:19
I'm afraid you should use thread, i.e. move all SQL-queryies in separate thread and establish communication between main thread and worker thread using signals/slots mechanism.
That would require rewritting the whole program. I am trying to avoid that :).

jpujolf
5th November 2009, 07:32
I made this specialized thread class :


#include <QThread>
#include <QSqlQuery>

class MyQueryThread : public QThread
{
QSqlQuery & m_Query;
QString m_SQL;

public :

MyQueryThread ( QSqlQuery & Query, const QString & SQL ) :
m_Query ( Query ), m_SQL ( SQL ) {}

void run ()
{
m_Query.exec ( m_SQL );
}
};

void ExecQueryWrapper ( QSqlQuery & Query, const QString & SQL )
{
MyQueryThread MQT ( Query, SQL );
MQT.start();
while ( MQT.isRunning() )
qApp->processEvents ();
};


You only have to wrap your call to exec through this function and all calls are made without freezing GUI.

faldzip
5th November 2009, 08:22
I made this specialized thread class :


#include <QThread>
#include <QSqlQuery>

class MyQueryThread : public QThread
{
QSqlQuery & m_Query;
QString m_SQL;

public :

MyQueryThread ( QSqlQuery & Query, const QString & SQL ) :
m_Query ( Query ), m_SQL ( SQL ) {}

void run ()
{
m_Query.exec ( m_SQL );
}
};

void ExecQueryWrapper ( QSqlQuery & Query, const QString & SQL )
{
MyQueryThread MQT ( Query, SQL );
MQT.start();
while ( MQT.isRunning() )
qApp->processEvents ();
};


You only have to wrap your call to exec through this function and all calls are made without freezing GUI.

I'm afraid it is not a good example code as QSqlDatabase connection does not support multithreading. So when you want to use database in a thread you have to create new database connection in every thread. And remember that in QThread class only the body of run() method is in separate thread, body of the QThread constructor for example (so constructing member variables) is in the constructors caller thread. So for eaxample creating connection to database (so queries using that connection also) sould be done in run() method and they sould be run() method local variables or created on a heap in run() thread (then you can have member pointer variables).

jpujolf
5th November 2009, 08:47
I didn't share your point of view. I agree QSqldatabase is not multithread. But take a better look at my code, please, before blaming it.

I disagree in the fact that this piece of code is not working, because is currently in a production software and I have no problems with it. Sometimes reality comes and shows you're wrong...

If you take a closer look at the code, you can see I DON'T execute multiple threaded calls to the database. I suggested to wrap the call, that locks the main thread whith a "working" while that allows GUI to show updates, mouse / window movements, etc.

I proposed a wrapped call to avoid re-writing entire program, but allowing the GUI stay active wile running slow queries. It works, as I said before. And is simple to replace a call like this :


QSqlQuery Qry;
Qry.exec ( "SELECT * FROM FAR_TABLE" )


to one like this



QSqlQuery Qry;
ExecQueryWrapper ( Qry, "SELECT * FROM FAR_TABLE" )


without great effort...