How to know thread is running from different button ?



  • Dear All,

    I create a button and make it run a infinity loop thread:

    void MainWindow::on_pushButton_2_clicked()
    {
        MyThread  *T3Thread = new MyThread;
        T3Thread->start(); // <-- in run is a infinity loop with delay(20)
    }
    

    Now I want to check if T3 thread is running by

    void MainWindow::on_pushButton_3_clicked()
    {
        MyThread  *T3Thread = new MyThread;
        if(T3Thread->isRunning())
            qDebug()<<"T3 thread is running";
    }
    

    I believe everyone can see the mistake, T3Thread in button_2 is different from button_3 so T3Thread->isRunning() will never return true.

    What should I do ?

    Thanks for any suggestions.



  • t3 just a local variable?Why not use member variables



  • @a-normal-worker said in How to know thread is running from different button ?:

    t3 just a local variable?Why not use member variables

    Do you mean a global variable ?



  • @a-normal-worker said in How to know thread is running from different button ?:

    t3 just a local variable?Why not use member variables

    If I change T3Thread to global variable, then I met a different situation:
    I wrote a myThread.h, inside this header file, I create a "my thread class":

    class MyThread : public QThread
    {
        Q_OBJECT
    
    signals:
        
    
    private:
        void run()
         {
            while(1)
            {
                for (int i = 0; i <= 100; i++)           
                    delay(20);  
            }
         }
    };
    

    In order to declare a global variable, I add this line to mainwindow.h :

    private:
         MyThread *T3Thread;
    

    However, because mainwindow.h do not know "MyThread", so I include "myThread.h" to mainwindow.h.
    Then compiler said "redefine of class xxxxx"

    So....I cannot include another header file ? How to declare a variable like "MyThread *T3Thread" correctly.

    Thanks everyone.


  • Moderators

    @Hiloshi Does your myThread.h header file has an "include guard"? See https://en.wikipedia.org/wiki/Include_guard
    They usually look like:

    #ifndef MYTHREAD_H
    #define MYTHREAD_H
    class MyThread...
    #endif
    

    Another note: since T3Thread is a pointer you do not need to include myThread.h in mainwindow.h. Instead use forward declaration:

    // In mainwindow.h before MainWindow class
    class MyThread;
    

    and include myThread.h in mainwindow.cpp.

    One more note: T3Thread is NOT a global variable (and this is good), it is an class member variable.



  • @Hiloshi Maybe my idea is not clear. Your code is created with two different objects, so their states are different. You should make sure that you use a class member variable or they point to the same object


  • Moderators

    @a-normal-worker "You should make sure that you use a class member variable or they point to the same object" - he already does in his last post.



  • Dear @jsulm , @a-normal-worker ,

    Thank you all. First, the "redefine of class xxxxx" issue may cause by a silly mistake:

    #ifndef MYTHREAD_H
    #define MYTHREAD_H
    #endif 
    class MyThread   // <--I put my code here.
    

    After fix above mistake and declare T3Thread pointer correctly then can compiler successfully.

    But running the program show a strange message: "Process killed by signal"

    In MyThread.h:

    class MyThread : public QThread
    {
        Q_OBJECT
    
    private:
        void run()
         {       
            for (int i = 0; i <= 100; i++)
            {            
                delay(20);
            }       
         }
    };
    

    In mainwindow.h:

    class MyThread;
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        explicit MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    private slots:
        void on_pushButton_pressed();
    
        void on_pushButton_2_clicked();
    
    private:
        Ui::MainWindow *ui;
        MyThread *T3Thread;
    };
    

    In mainwindow.cpp:

    #include "mythread.h"
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);   
        MyThread  *T3Thread = new MyThread;
        T3Thread->start();
    }
    void MainWindow::on_pushButton_12_clicked()
    {
        T3Thread->start();
    }
    

    When I run the program, the screen show as normal, but when I press button_2, the screen close suddently, and show "Process killed by signal" on QT terminal.

    I suspect that problem is cause by T3Thread->start(), however, if I didn't press button_2, nothing happened.
    T3Thread should also executed while creating main window?

    Do I lack some declaration ?


  • Lifetime Qt Champion

    Your constructor is wrong. You are shadowing your T3Thread member variable. Thus when you call on_pushButton_12_clicked you are trying to access an uninitialised pointer hence the crash.


  • Moderators

    @Hiloshi To add to @SGaist : why do you start the thread twice (once in the constructor and then in on_pushButton_12_clicked())?



  • Dear @jsulm , @SGaist

    Sorry to confuse you, I didn't explain clearly.

    If I use "new" and "T3Thread->start" in the same area, then it will no error(process killed by signal),
    as below:
    https://www.dropbox.com/s/0488sqlhgn9u4wf/Screenshot from 2017-04-06 09-28-32.png?dl=0
    alt text

    However, if I put them in different place, application will crash and return "process killed by signal",
    as below:
    https://www.dropbox.com/s/3dfists06z3c5q9/Screenshot from 2017-04-06 09-33-10.png?dl=0
    alt text

    Moreover, if I put "new" just after the "ui->setupUi(this)" and "T3Thread in the on_pushButton_clicked,
    it will show a warning message "unused variable ‘T3Thread’ [-Wunused-variable]".

    @SGaist , I think maybe this is what you said : "uninitialised pointer " .

    But, I am sorry, I don't know how to correct it.


  • Lifetime Qt Champion

    Remove MyThread * from your constructor.


  • Moderators

    @Hiloshi You should really read more carefully what others are writing. What @SGaist said is:

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);   
        T3Thread = new MyThread; // Remove MyThread* - else you are declaring a local variable which is completely unrelated to the one in your header!
        T3Thread->start();
    }
    

    And after this change think about where to start the thread: in the code you posted you're doing it twice.



  • Very happy to learn from here. Thanks everyone.



  • I want to study in depth in this question. In the original question, I have a running T3Thread, mainwindow cannot reach T3Thread, thanks for @a-normal-worker 's suggestion, we can make T3Thread as a class member of mainwindow then mainwindow have ability to access T3Thread.

    Can we use signal/slot instead of using class member ?


  • Lifetime Qt Champion

    What exactly do you want to do with your thread ?



  • Dear @SGaist ,

    I am thinking to create a breathing LED in my thread, "run" function is keep turn on/off LED.
    I want to put one button on mainwindow to start the thread.

    I do not want this button to be pressed twice ( or thread will create twice), so in the button I put:

    void MainWindow::on_pushButton_3_clicked()
    {
        if(T3Thread->isRunning()==false)
        {
            MyThread  *T3Thread = new MyThread;  // local variable
            T3Thread->start;
        }
        else
            qDebug()<<"T3 thread is running";
    }
    

    If I do not want to use class member, can I use signal/slot to know T3Thread is running or not ?

    Thanks.



  • @Hiloshi
    ok, I think we talk at cross here.

    Here's a basic setup to check if your thread is running when you press a Button, if its not running the button will start the thread:

    //in your header:
    example.h
    
    #include <QThread>
    #include <qDebug>
    
    private:
    QThread *thread;
    
    //in your source file
    
    //Constructor
    {
        ui->setupUi(this);   
        thread = new QThread;
    ....
    }
    
    
    void on_pushButton_clicked(){
       if(thread->isRunning())
          qDebug() << "Thread is running";
       else{
          qDebug() << "Thread started";
          thread->start(); 
       }
    }
    
    //Destructor
    {
      if(thread->isRunning()){
       thread->quit();
       thread-> wait();
      }
    ...
      delete ui;
    }
    

  • Lifetime Qt Champion

    What is the problem with using a member variable to handle that thread object properly ?



  • @SGaist , There is no problem using member variable. I just thinking if it possible to use signal/slot to reach the same purpose.


  • Lifetime Qt Champion

    There could be ways however you are talking about creating an object somewhere without any reference to it and still want to interact with it. That's bad by design.



  • @SGaist , Understood, thanks for the help.


Log in to reply
 

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