Antonio Del Sannio
Antonio Del Sannio

Reputation: 315

QT QThread::isrunning freeze program on Pi

I'm testing a programm on my PI.When running it on the host pc no error is shown, instead , running it on pi (CM3) it freezes.

I'm trying to use multithreading.

From the main thread, in the constructor an QThread is started, then when I click on the button to open a new form the GUI freezes. In the button slot I need to check if the serial_works thread has been started in the constructor has finished before opening a new form, so I added a QThread::isRunning() check;

Main_Form::Main_Form(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::Main_Form)
{
    ui->setupUi(this);
    this->move(0,0);
    this->setWindowFlags(Qt::Window | Qt::FramelessWindowHint);         
    connect(ui->btn,SIGNAL(clicked(bool)),this,SLOT(open_form()));
    *serial_works = new SerialWorks();
    serial_works->start();
}

void Main_form::open_form(){
std::cout<<"open form slot"<<std::endl;
int i = 0;
while(serial_works->isRunning()){
    std::cout<<"WHILE"<<std::endl;
    QThread::msleep(100);
    i++;
    if(i > 10){
        serial_works->terminate();
    }
Next_form *frm = new Next_form();
this.close();
frm->show();
}

the run method in the Serial_works class is

void Serial_works::run() {
   my_function();
   this->terminate();
   this->wait();
}

void Serial_works::my_function(){
  ....stuff on serial
  std::cout<<"serial works finished"<<std::endl;
}

on the output i get

 //serial works finished
 //open_slot_form

no WHILE is printed out on the console,thus the program get stuck on the while check

serial_works->isRunning()

Where is the problem? On the the host pc, the new form opens as expected.

Upvotes: 0

Views: 504

Answers (1)

UmNyobe
UmNyobe

Reputation: 22910

You are trying to use QThread without understanding what is this object doing. What you want to do is asynchronous execution : Do some work and when you are done let me know.

Edit : What is Happening :

  • Client : main thread executes open_form before the worker executes run
  • Rasberry Pi : worker executes run before main thread executes open_form

On PI

  1. serial_works->start() launch worker, which execute first, and complete my_function.
  2. worker call this->terminate() and is now officially dead. terminate is a brutal way of stopping a QThread..I cannot even speculate whether wait() is called.
  3. The main thread execute open_form, and the worker is already non-runnable. So the loop is not executed and Next_form is never going to be shown.

Error 1 :

Main_form::open_form()

is executing in the gui thread, and you are sleeping on a event. This is always incorrect. You GUI will freeze for the amout of time you are sleeping. Use signals and slots or events.

Error 2 :

Serial_works is likely a subclass of Qthread. You are confusing a thread of execution with the object managing that thread. You should not subclass QThread.

   this->terminate();
   this->wait();

The worker thread is executing that code. You are killing yourself then waiting on your death. So depending on the implementation you may wait forever , crash, etc....

What you need to do : Use QFuture and QFutureWatcher.

//inside Main_Form
QFutureWatcher<ReturnValueType> watcher;

void Main_form::open_form(){
    // Instantiate the objects and connect to the finished signal.
    connect(&this->watcher, SIGNAL(finished()), &this, SLOT(SignalWorkFinished()));

    // Start the computation.
    QFuture<ReturnValueType> future = QtConcurrent::run(stuffOnSerialFunction);
    this->watcher.setFuture(future);
}

// now handle work finish
void SignalWorkFinished()
{
   QFuture<ReturnValueType> future = watcher.future();
   //do whatever you like
}

Upvotes: 1

Related Questions