I am trying to connect my Qt application to a database. Since I have a GUI, of course the only way to do this is in a separate thread. I found out that I can do it via QtConcurrent::run
. Here is my code:
MainWindow::MainWindow(QWidget *parent) {
// ...
QFuture<bool> worker = QtConcurrent::run(this, &MainWindow::connectDatabase);
QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>;
connect(watcher, &QFutureWatcher<bool>::finished, this, &MainWindow::databaseConnected);
watcher->setFuture(worker);
}
bool MainWindow::connectDatabase() {
QSqlDatabase db = QSqlDatabase::addDatabase("QPSQL");
db.setHostName("127.0.0.1");
db.setUserName("user");
db.setPassword("pass");
db.setDatabaseName("mydb");
return db.open();
}
It works but I am not able (obviously) to get any data out of the process. For example, I would like to know if the connection succeeded and it would be ideal if I could get it through the slot.
I could add the watcher
as a member of the class and query it from the slot but this approach would be tedious for many async task I believe.
What should I do?
You have to make worker
a class member (because the local variable will be deleted on exit from the constructor):
MainWindow::MainWindow(QWidget *parent) {
// ...
m_worker = QtConcurrent::run(this, &MainWindow::connectDatabase);
QFutureWatcher<bool> *watcher = new QFutureWatcher<bool>;
connect(watcher, &QFutureWatcher<bool>::finished, this, &MainWindow::databaseConnected);
watcher->setFuture(m_worker);
}
Way 2:
MainWindow::MainWindow(QWidget *parent) {
connect(this, &MainWindow::mySignalAboutDBOpen,
this, &MainWindow::databaseConnected, Qt::QueuedConnection);
QtConcurrent::run(this, &MainWindow::connectDatabase);
}
//and in the connectDatabase:
bool MainWindow::connectDatabase() {
//...
bool ret = db.open();
emit mySignalAboutDBOpen(ret);
return ret;
}
Please note that the QSqlDatabase db
variable also is local and will be deleted on exit of connectDatabase()
.