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)
Try executing the whole task in a run
, e.g.
QtConcurrent::run([](){
SqlFetcher m_Fetcher;
m_Fetcher.createDb();
m_Fetcher.qint64TotalSize();
});
Since we're dealing with concurrency, it's safer to use named connections (otherwise the same default connection will be used every time, possibly by more than one thread). You can manage this by adding an argument to SqlFetcher::createDb
:
void SqlFetcher::createDb(const QString & connectionName)
{
m_sqldb = QSqlDatabase::addDatabase("QSQLITE", connectionName);
// etc.
and to the lambda and the run
function, as well:
QtConcurrent::run([](const QString & cn){
SqlFetcher m_Fetcher;
m_Fetcher.createDb(cn);
m_Fetcher.qint64TotalSize();
}, QString("TheConnectionName"));
In the other function, assign the database to the query, in construction:
void SqlFetcher::qint64TotalSize()
{
qint64 l_result= 0;
QSqlQuery l_query(m_sqldb);
//etc.