Search code examples
c++qtqtconcurrent

Getting data out QFutureWatcher


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?


Solution

  • 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().

    See Qt::ConnectionType