Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

How to use QThread?



  • Hello, I'm making some GUI through QT.
    I almost complete my work but QThread doesn't work. When I click the measure button, my GUI just terminates.
    My goal is to measure the position of the encoder (it moves) and display it on the Qtextbrowser. Can you figure out what I did wrong?
    MDCE is a class in mpint.h

    //position.h
    #ifndef POSITION_H
    #define POSITION_H
    
    #include "mpint.h"
    #include <QThread>
    #include <QTextBrowser>
    
    class position :public QThread
    {
        Q_OBJECT
    public:
        position(QThread* parent = nullptr);
        ~position();
        double CurrentLocation(MDCE* com);
        void StartThread(MDCE* com, QTextBrowser* browser);
        void MeasureLocation(MDCE* com, QTextBrowser* browser);
        void stopMeasure();
    private:
        QThread* thread1;
    
    };
    
    
    
    #endif // POSITION_H
    
    //position.cpp
    #include "position.h"
    
    
    position::position(QThread* parent) : QThread(parent)
    {
        thread1 = nullptr;
    }
    
    // Destructor
    position::~position()
    {
        if (thread1 != nullptr)  delete thread1;
    }
    
    
    double position::CurrentLocation(MDCE* com)
    {
        char record[] = "X_enc_pos";
        double location;
        GetVarN(record, &location, 0, com); //this function puts the value of current position to (double) location
        return location;
    }
    
    void position::MeasureLocation(MDCE* com, QTextBrowser* browser)
    {
        double location;
        while (1)
        {
            location = CurrentLocation(com);
            browser->setText(QString::number(location));
            if (QThread::currentThread()->isInterruptionRequested()) return;
        }
    }
    
    void position::StartThread(MDCE* com, QTextBrowser* browser)
    {
    
        thread1 = QThread::create(std::bind(&position::MeasureLocation,this, com, browser));
        thread1->start();
    }
    
    
    void position::stopMeasure()
    {
        thread1->requestInterruption();
        if (!thread1->wait(3000))
        {
            thread1->terminate();
            thread1->wait();
        }
        thread1 = nullptr;
    }
    

    Thank you :)


  • Lifetime Qt Champion

    Hi and welcome to the forums.

    You are not allowed to use QTextBrowser * directly from a thread.
    That will crash.
    You must send a signal to main thread and it will talk to the text browser.

    No QWidget of any kind can be directly accessed from threads.


  • Lifetime Qt Champion

    Hi and welcome to the forums.

    You are not allowed to use QTextBrowser * directly from a thread.
    That will crash.
    You must send a signal to main thread and it will talk to the text browser.

    No QWidget of any kind can be directly accessed from threads.


  • Qt Champions 2019

    @H-dragon To add to @mrjj : why do you inherit QThread and then add a QThread* member?


  • Moderators

    Hi, and welcome!

    @H-dragon said in How to use QThread?:

    class position :public QThread
    {
        ...
    private:
        QThread* thread1;
    };
    

    Your position class inherits QThread and contains a QThread (thread1) at the same time. I'm sure that's not what you want! (EDIT: @jsulm beat me to it)

    Start by studying some examples, like:



  • You are missing some fundamental concepts of QThread but it's not your fault, this stuff is complicated and the docs, while they improved a lot, still appear confusing to newcomers. Have a look at https://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/ it's a great read to fix the QThread concept in mind



  • GUI.png
    @mrjj @jsulm @JKSH @VRonin, Sorry for late reply and Thank you so much! I thought that It will take time to get answer, but you answered right away. I understand that I misunderstood the concept of inheritance.

    But I have another question reading your answers and examples - does QThread require the void function to put all the function in one window? I'm making GUI like the picture I uploaded, which displays the position in the red rectangular line (ex. 50000 count).
    @mrjj said I'm not allowed to use QTestBrowser directly, so I deleted the QtextBrowser and changed working function from void to double like below

    //position.h
    #ifndef POSITION_H
    #define POSITION_H
    
    #include "mpint.h"
    #include <QThread>
    
    class position
    {
    
    public:
        position();
        ~position();
        double CurrentLocation(MDCE* com);
        void StartThread(MDCE* com);
        void MeasureLocation(MDCE* com);
        void stopMeasure();
    private:
        QThread* thread1;
    
    };
    
    #endif // POSITION_H
    
    #include "position.h"
    
    
    position::position()
    {
        thread1 = nullptr;
    }
    
    // Destructor
    position::~position()
    {
        if (thread1 != nullptr)  delete thread1;
    }
    
    
    double position::CurrentLocation(MDCE* com)
    {
        char record[] = "X_enc_pos";
        double location;
        GetVarN(record, &location, 0, com);
        return location;
    }
    
    
    void position::StartThread(MDCE* com)
    {
    
        thread1 = QThread::create(std::bind(&position::MeasureLocation,this, com));
        thread1->start();
    }
    
    double position::MeasureLocation(MDCE* com)
    {
        double location;
        while (1)
        {
            location = CurrentLocation(com);
            return location;
            if (QThread::currentThread()->isInterruptionRequested()) return;
        }
    }
    
    void position::stopMeasure()
    {
        thread1->requestInterruption();
        if (!thread1->wait(3000))
        {
            thread1->terminate();
            thread1->wait();
        }
        thread1 = nullptr;
    }
    
    //mainwindow.cpp(this isn't the entire code)
    
    connect(ui->btnMeasurePos, SIGNAL(clicked()), this, SLOT(getPosition()));
    
    
    void MainWindow::getPosition()
    {
        double posval;
        pos.StartThread(motor);
        //I want to get the position double value in some ways
        ui->statusEncoder->settext~~~~~
        //display in QTextBrowser
        //motor is MDCE class, statusEncoder is QTextBrowser
    }
    

    but as I write in mainwindow, I don't know how to display the position while not blocking the main thread works(like move axis). how should I do?
    Sorry for my poor knowledge about C++ and QT.


  • Qt Champions 2019

    @H-dragon said in How to use QThread?:

    does QThread require the void function to put all the function in one window?

    QThread has nothing to do with windows and you should never change UI from other threads than main thread (this was already mentioned here I think). Your other threads should simply emit signals which can be connected to slots in your UI.

    Did you read what @VRonin suggested to read? I don't know what you're trying to achieve with your latest code...

    Are you actually sure you need threads at all?


Log in to reply