QT QThread::isrunning 冻结程序在 Pi

Posted

技术标签:

【中文标题】QT QThread::isrunning 冻结程序在 Pi【英文标题】:QT QThread::isrunning freeze program on Pi 【发布时间】:2017-10-27 09:26:23 【问题描述】:

我正在我的 PI 上测试一个程序。在主机 pc 上运行它时没有显示错误,相反,在 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,因此程序卡在while检查中

serial_works->isRunning()

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

【问题讨论】:

我无法回答您的问题,但我认为如果您列出主机架构、编译器和编译器以及在 Pi 和主机上使用的链接器标志会有所帮助? 你留下了最重要的部分,比如 "....stuff on serial" 我已经用 ./configure -no-use-gold-linker -release -opengl es2 -device linux-rasp-pi3-vc4-g++ -device-option CROSS_COMPILE=~/raspi 编译了 QT /tools/arm-bcm2708/gcc-linaro-arm-linux-gnueabihf-raspbian/bin/arm-linux-gnueabihf- -sysroot ~/raspi/sysroot -opensource -make libs -prefix /usr/local/qt5pi -extprefix ~ /raspi/qt5pi -hostprefix ~/raspi/qt5 -v 这样就可以知道架构了,my_function实现我就省略了,因为问题不存在,函数返回,串口已经关闭 Linux 版本 4.9.58-v7+ (dc4@dc4-XPS13-9333) (gcc 版本 4.9.3 (crosstool-NG crosstool-ng-1.22.0-88-g8460611)) 【参考方案1】:

你试图使用 QThread 却不了解这个对象在做什么。您要做的是异步执行做一些工作,完成后告诉我

编辑:发生了什么

客户端:主线程在worker执行run之前执行open_form Rasberry Pi:worker 在主线程执行之前执行 run open_form

在 PI 上

    serial_works->start() 启动worker,先执行,完成my_function。 工人致电this-&gt;terminate(),现已正式死亡。 terminate is a brutal way of stopping a QThread..我什至无法推测是否调用了 wait()。 主线程执行open_form,worker已经不可运行。所以循环不会被执行并且 Next_form 永远不会被显示出来。

错误 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

【讨论】:

但是在主机 pc 上代码可以工作,我很抱歉,但为什么我要在一个事件上睡觉?在 QThread::msleep(100) 之后,我检查第二个线程是否已经完成并且在那如果代码一直持续到 frm->show(); 为什么没有打印出“WHILE”? 好吧,我明白了,但怎么可能在主机上打开表单?为什么它在 Pi 上而不是主机上冻结?

以上是关于QT QThread::isrunning 冻结程序在 Pi的主要内容,如果未能解决你的问题,请参考以下文章

使用协程流程->收集时房间冻结

Qt 调试器在 OpenCV 中冻结

Qt:如何在特定时间内冻结某些按钮?

Python中的冻结Qt GUI

退出时删除 QQuickView 会导致 Qt 应用程序冻结

尝试获取文件的 MD5 时 Qt 程序冻结