[Solved]Proper Usage of QThread
-
Hi
I wanted to use QThread at some point in order to remove the weight from GUI thread. So i went ahead and started reading how to properly use QThread since threads are generally dangerous.
So i found this:
http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/I added that to my program:
class WorkerRearrange : public QObject { Q_OBJECT public: WorkerRearrange(MainWindow * mainWin, qint32 startingFrom); ~WorkerRearrange(); void setValues(MainWindow * mainWin, qint32 startingFrom); public slots: void process(); signals: void finished(); void error(QString error); private: MainWindow * m_mainWin; qint32 m_startingFrom; };
and in the MainWindow class
QThread * thread = new QThread; WorkerRearrange * worker = new WorkerRearrange(this, startingFrom); connect(thread, SIGNAL(started()) , worker, SLOT(process())); connect(worker, SIGNAL(finished()) , thread, SLOT(quit())); connect(worker, SIGNAL(finished()) , worker, SLOT(deleteLater())); connect(thread, SIGNAL(finished()) , thread, SLOT(deleteLater())); connect(worker, SIGNAL(finished()) , this, SLOT(onRearrangeFinished())); worker->moveToThread(thread); thread->start();
and here is the process() function
void WorkerRearrange::process() { if(m_mainWin != nullptr) { m_mainWin->ui->treeWidgetData->setColumnCount(m_mainWin->getColumns().count()); m_mainWin->ui->treeWidgetData->setHeaderLabels(m_mainWin->getColumns()); QStringList tempColumnHeaders = m_mainWin->getColumns(); tempColumnHeaders.append(SQLDB_TABLE_COLUMN_ID); QSqlQuery query = SqliteWrapper::readEntriesFromSQLDB(m_mainWin->getDB() , SQLDB_TABLE_CURRENT , tempColumnHeaders , m_startingFrom); m_mainWin->ui->treeWidgetData->clear(); m_mainWin->m_IDs.clear(); while(query.next() == true) { QTreeWidgetItem * item = new QTreeWidgetItem(); item->setFlags(Qt::ItemIsEnabled | Qt::ItemIsSelectable); m_mainWin->m_IDs.append(query.value(SQLDB_TABLE_COLUMN_ID).toInt()); for(qint32 i = 0; i < m_mainWin->getColumns().count(); i++) { item->setText(i, query.value(m_mainWin->getColumns().at(i)).toString()); } m_mainWin->ui->treeWidgetData->addTopLevelItem(item); } } emit finished(); }
My problem is when i run the application, although nothing seems wrong, i get the following output:
QObject::connect: Cannot queue arguments of type 'Qt::Orientation' (Make sure 'Qt::Orientation' is registered using qRegisterMetaType().) QObject::connect: Cannot queue arguments of type 'Qt::Orientation' (Make sure 'Qt::Orientation' is registered using qRegisterMetaType().) QObject::connect: Cannot queue arguments of type 'Qt::Orientation' (Make sure 'Qt::Orientation' is registered using qRegisterMetaType().)
What could be the problem, i searched but couldn't find what is wrong. I assume it has something to do with signal/slot connecting from different threads, but don't have any idea how to solve.
Thanks in advance for any help.
-
I'm no expert on this stuff, but my instinct looking at what you're doing is there's far to much "GUI stuff" going on in the thread. Leave that stuff on the main thread where it belongs; just use a thread for the bit which is actually slow/blocking, which I'm guessing involves the QSqlQuery. Better still forget QThread and use a higher level abstraction like QFuture & QtConcurrent::run (see also https://bugreports.qt.io/browse/QTBUG-17220 )
-
Hi,
You should rather read the QThread documentation, it's pretty complete by now and shows all possibilities.
You should not try to update GUI element from another thread, use Qt's signals and slots for communicate from your thread back to your widgets in the main thread.