QT C++ работа с базой данных в разных потоках

106
09 сентября 2019, 18:00

Как можно модифицировать ПО для мультипоточной работы.

Хотелось бы увидеть минимальный базовый пример, дабы разобраться и пока не лезть в дебри.

Есть большая таблица(100 тыс наименований) при их запросе виснет GUI. Хотелось бы это устранить.

Логика была такая.

  1. Человек открывает программу.
  2. Конструктор формы отправил запрос потоку в БД.
  3. Строится каркас приложения.
  4. Берём данные из потока в основной.
  5. Заполняем полученными данными таблицу.

p.s Пробовал сделать подобное на сигналах и слотах с применением QThread. Отправлял запрос в другой поток, но он начинал работать только когда закроется основное приложение...

mainwindow.СPP

#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
}
MainWindow::~MainWindow()
{
    delete ui;
}
void MainWindow::on_pushButton_clicked()
{
    //QSqlDatabase objDatabase;
    objDatabase = QSqlDatabase::addDatabase("QMYSQL");
    objDatabase.setDatabaseName("librarydb");
    objDatabase.setHostName("127.0.0.1");
    objDatabase.setPort(3306);
    objDatabase.setUserName("hays0503");
    objDatabase.setPassword("hays0503");
    objDatabase.open();
    //QSqlTableModel *objTableModel;
    objTableModel = new QSqlTableModel();
    objTableModel->setTable("author");
    if (!objTableModel->select())
    {
        qDebug()<<"Error";
    }else {
       ui->tableView->setModel(objTableModel);
    }
}

mainwindow.H

#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
#include <QDebug>
#include <QSql>
#include <QSqlError>
#include <QSqlDatabase>
#include <QSqlTableModel>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
    Q_OBJECT
public:
    explicit MainWindow(QWidget *parent = nullptr);
    ~MainWindow();
private slots:
    void on_pushButton_clicked();
private:
    Ui::MainWindow *ui;
    QSqlDatabase objDatabase;
    QSqlTableModel *objTableModel;
};
#endif // MAINWINDOW_H
Answer 1
void MainWindow::on_pushButton_clicked()
{
    QFuture<QSqlTableModel*> future = QtConcurrent::run(
        [this]() 
        {
            // Исполняем этот код в другом потоке
            //QSqlDatabase objDatabase;
            objDatabase = QSqlDatabase::addDatabase("QMYSQL");
            objDatabase.setDatabaseName("librarydb");
            objDatabase.setHostName("127.0.0.1");
            objDatabase.setPort(3306);
            objDatabase.setUserName("hays0503");
            objDatabase.setPassword("hays0503");
            objDatabase.open();
            //QSqlTableModel *objTableModel;
            objTableModel = new QSqlTableModel(this);
            objTableModel->setTable("author");        
            if (!objTableModel->select())
            {
                delete objTableModel;
                objTableModel = nullptr;
                qDebug()<<"Error";
            }
            return objTableModel;
        });
    QFutureWatcher<QSqlTableModel*> *watcher = new QFutureWatcher<QSqlTableModel*>(this);
    connect(watcher, SIGNAL(finished()), watcher, 
        [this, watcher]()
        {
            // Запускаем этот код в UI потоке, когда объект future завершит свою работу в рабочем потоке
            ui->tableView->setModel(watcher->result());
            watcher->deleteLater(); // Удалим ненужный watcher
        }, Qt::QueuedConnection);
    );
     watcher->setFuture(future); // Связываем watcher с feature. Это быстрая операция и не тормозит поток UI
}

Если много раз кликать на кнопку, то будет запущено сразу много одинаковых задач. Надо не забывать, что работать с объектами objDatabase и objTableModel можно только из одного потока одновременно.

READ ALSO
Отличие между const string &amp;s и string &amp;s

Отличие между const string &s и string &s

столкнулся с одной проблемой, и не могу понять, почему так происходит

93
Как добавить большой список слов в вектор?

Как добавить большой список слов в вектор?

Нужно добавить большой список слов в вектор

112
sprintf - формирование нескольких подсрок с использованием одного параметра

sprintf - формирование нескольких подсрок с использованием одного параметра

Подскажите, можно ли реализовать следующую задумку:

91
Ошибка считывания/записи переменной в 3х потоках с использованием atomic и без (с++)

Ошибка считывания/записи переменной в 3х потоках с использованием atomic и без (с++)

У нас есть 2 потока, которые асинхронно записывают в переменную tmp числа 322 и 1337Странность в том, что даже если переменная atomic, условие все-таки...

103