QT QThread ::在Pi上运行冻结程序

时间:2017-10-27 09:26:24

标签: c++ qt qthread

我在我的PI上测试程序。当在主机上运行它时没有显示错误,而是在pi(CM3)上运行它冻结。

我试图使用多线程。

从主线程中,在构造函数中启动QThread,然后当我单击按钮打开新表单时,GUI冻结。在按钮插槽中,我需要检查构造函数中的serial_works线程是否已经在打开新表单之前完成,所以我添加了一个QThread :: isRunning()检查;

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();
}

Serial_works类中的run方法是

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;
}
输出

 //serial works finished
 //open_slot_form

控制台上没有打印出WHILE,因此程序在检查时卡住了

serial_works->isRunning()

问题出在哪里?在主机PC上,新表单按预期打开。

1 个答案:

答案 0 :(得分:1)

您正在尝试使用QThread而不了解此对象正在做什么。您要做的是异步执行做一些工作,完成后请告诉我

编辑:发生了什么

  • 客户端:主线程在工作人员执行运行之前执行open_form
  • Rasberry Pi:worker在主线程执行open_form
  • 之前执行运行

关于PI

  1. serial_works-&gt; start()启动工作程序,首先执行,然后完成my_function。
  2. 工人致电this->terminate(),现在正式死亡。 terminate is a brutal way of stopping a QThread.。我甚至无法推测是否调用了wait()。
  3. 主线程执行open_form,worker已经不可运行。因此循环不会执行,Next_form永远不会显示。
  4. 错误1:

    Main_form::open_form()
    

    正在gui线程中执行,你正在睡觉。这总是不正确的。你的GUI会在你睡觉的时间内冻结。使用信号和插槽或事件。

    错误2:

    Serial_works可能是Qthread的子类。您正在将执行线程与管理该线程的对象混淆。 您不应该继承QThread

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

    工作线程正在执行该代码。你正在杀死 你自己 然后等待你的死亡。因此,根据实施情况,您可能会永远等待,崩溃等......

    您需要做什么: 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
    }