над чтобы долгий процесс загрузки данных с БД выполнялся независимо от главного потока(чтоб приложение не подвисало), и время от времени выводилось сообщение о выполнении процесса.. щас решил сделать 2 потока: один будет посылать главному приложению сообщения о процессе выполнения а второй будет выполнять запросы к бд, как только 2й поток закончит выполнение то оба потока завершают свою работу.. и вроде все честно сделал но проблема в том что работает оно нестабильно - всмысле при выполнении одних и тех-же запросов - результат выводится неполностью или выдаются ещё пустые строки и количество QSqlQueryModel::rowCount() выдается разное.. итак: поток который сообщает о процессе выплнения главному приложению | Код | class MyThread : public QThread { Q_OBJECT public:
MyThread_exec *m_MyThread_exec; //поток который выполняет запрос
QLineEdit *m_QLineEdit_exec; // куда выводим время вып-я QLineEdit *m_QLineEdit_rows; // кол-во стрк
QTableView *m_QTableView; QString m_sql;
QTime time;
public: MyThread(); ~MyThread();
void set_sql (QTableView *p_QTableView, QLineEdit *p_exec, QLineEdit *p_QLineEdit_rows, const QString &p_sql);
void run();
public slots: void stopThread();
signals: void set_time_text(const QString &p_txt); void set_rows_text(const QString &p_txt);
}; ..... /////////////////////////////////////////////////////////////////////////////////////////////////// MyThread::MyThread() :m_QTableView(0), m_MyThread_exec(new MyThread_exec(this)), m_QLineEdit_exec(0) { qDebug() << "MyThread::MyThread() begin "<< QString::number( (int)this,16 );
QObject::connect( m_MyThread_exec, SIGNAL( finished ()) , this , SLOT( stopThread()) ); QObject::connect( m_MyThread_exec, SIGNAL( terminated()) , this , SLOT( stopThread()) ); QObject::connect( this, SIGNAL( terminated()) , m_MyThread_exec , SLOT( terminate()) );
} /////////////////////////////////////////////////////////////////////////////////////////////////// MyThread::~MyThread() { m_MyThread_exec->terminate(); delete m_MyThread_exec; terminate(); } /////////////////////////////////////////////////////////////////////////////////////////////////// void MyThread::set_sql (QTableView *p_QTableView, QLineEdit *p_exec, QLineEdit *p_QLineEdit_rows, const QString &p_sql) { m_QTableView=0; m_QLineEdit_exec=p_exec; m_QLineEdit_rows=p_QLineEdit_rows; m_sql=p_sql; } /////////////////////////////////////////////////////////////////////////////////////////////////// void MyThread::stopThread() { m_MyThread_exec->terminate (); terminate ();
emit set_time_text( QString("%1").arg( ((double)time.elapsed())/1000,10,'f',2 ) ); // выводим время вып-я emit set_rows_text( QString::number( m_MyThread_exec->m_model->rowCount() ) ); // кол-во строк
} /////////////////////////////////////////////////////////////////////////////////////////////////// void MyThread::run() { QObject:: connect( this, SIGNAL( set_rows_text(const QString &) ) , m_QLineEdit_rows , SLOT( setText(const QString &) ) ); QObject:: connect( this, SIGNAL( set_time_text(const QString &) ) , m_QLineEdit_exec , SLOT( setText(const QString &) ) ); m_MyThread_exec->start(); time.start(); while(1) { emit set_time_text( QString("%1").arg( ((double)time.elapsed())/1000,10,'f',2 ) ); // выводим время вып-я emit set_rows_text( QString::number( m_MyThread_exec->m_model->rowCount() ) ); // кол-во строк msleep(50);
} quit(); } ///////////////////////////////////////////////////////////////////////////////////////////////////
|
поток который выполняет запрос | Код | class MyThread_exec : public QThread { public:
QSqlDatabase m_db; //для этого потока создаем отдельное подключение к бд QSqlQueryModel *m_model;
MyThread *m_MyThread;
//MyThread_exec(QSqlQueryModel *p_model,MyThread *p_MyThread);
MyThread_exec(MyThread *p_MyThread); ~MyThread_exec(); void run();
}; ... /////////////////////////////////////////////////////////////////////////////////////////////////// MyThread_exec::MyThread_exec(MyThread *p_MyThread) :m_db(), m_model(new QSqlQueryModel() ), m_MyThread(p_MyThread) { m_db = QSqlDatabase::addDatabase( tr("QODBC"),"connect_name__test_" ); } /////////////////////////////////////////////////////////////////////////////////////////////////// MyThread_exec::~MyThread_exec() { terminate(); m_model->clear(); delete m_model; m_db.close(); } /////////////////////////////////////////////////////////////////////////////////////////////////// void MyThread_exec::run() {
m_db.close(); m_db.setDatabaseName( "test_dbf" );
if(!m_db.open()) { QMessageBox::information(0, QString("err"),m_db.lastError().text()); return ; }
m_model->setQuery( m_MyThread->m_sql , m_db);
while (m_model->canFetchMore()) { m_model->fetchMore(); msleep(100); } quit();
} ///////////////////////////////////////////////////////////////////////////////////////////////////
|
и как все это выполняем: | Код | void MainWindow::pushButton_test_on_clicked() {
if(!m_thread) { m_thread = new MyThread(); ui->tableView_all_records->setModel( m_thread->m_MyThread_exec->m_model ); }
// если не писать следующей строки то приложение иногда ведет себя ещё более неадекватно m_thread->m_MyThread_exec->m_model->moveToThread( QThread::currentThread() );
m_thread->set_sql(ui->tableView_all_records, ui->lineEdit_execute_time, ui->lineEdit_rows, "SELECT * FROM test_table" );
m_thread->start();
}
|
поток m_thread - уничтожаем тока после того как полученные данные уже будут не нужны, т.к. m_model - которая отображается в QtableView - находится в его дочернем потоке и уничтожается вместе с ним! вообщем проблема в том что в QtableView иногда выводится слишком много записей с пустыми строками, и иногда не все строки загружаются(выводятся пустыми)... подскажите как корректно решить задачку?
|