[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 )


  • Lifetime Qt Champion

    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.



  • @SGaist @timday

    Thank you guys for the advice. I changed it so GUI updates are done inside the GUI. Everything looks fine and Qt gives no error, or warning messages.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.