QThread quit()或finished()是何时完成的?

QThread quit()或finished()是何时完成的?,qt,qthread,Qt,Qthread,我是Qt新手,只想在QtGUI中显示视频。我基本上解决了所有问题,除了处理QThread的一些细节,这真的很烦人 我把我的问题重新整理成一个更简单的程序,希望它能更好地解释问题 首先我定义这个QObject类 #include <QObject> #include <QDebug> class myObject : public QObject { Q_OBJECT public: explicit myObject(QObject *parent = 0

我是Qt新手,只想在QtGUI中显示视频。我基本上解决了所有问题,除了处理QThread的一些细节,这真的很烦人

我把我的问题重新整理成一个更简单的程序,希望它能更好地解释问题

首先我定义这个QObject类

#include <QObject>
#include <QDebug>
class myObject : public QObject
{
    Q_OBJECT
public:
    explicit myObject(QObject *parent = 0);
    bool stop;

signals:
    void finishWork();

public slots:
    void dowork();
    void onfinishThread();

};

myObject::myObject(QObject *parent) :
QObject(parent)
{
    stop = true;
}

void myObject::dowork(){
    qDebug()<<"start working!";
    while(!stop){
        qDebug()<<"working...";
    }
    emit finishWork();
    qDebug()<<"finish do work!";
}
void myObject::onfinishThread(){
    qDebug()<<"thread is finished!";
}
输出完全相同!打印后只停留一段时间

线程还在运行

有人能帮我吗?谢谢。您可以简单地复制所有代码并自己进行测试


-------------------------原始问题,解释错误,请忽略----------------------------------------

我制作了一个videoObj类,其中只有一个查询帧的函数,该函数定义为:

void videoObj::ProcessFrame(){
bool getframe;
qDebug()<<"get in ProcessFrame";
while(!stop_flag){
    getframe = capture_.read(imgOriginal_);
    if(!getframe){
        qDebug()<<"Video End!";
        break;
    }
    cv::cvtColor(imgOriginal_, imgOriginal_, CV_BGR2RGB);
    QImage qimgOriginal((uchar*)imgOriginal_.data, imgOriginal_.cols, imgOriginal_.rows, imgOriginal_.step, QImage::Format_RGB888);

    emit imgProcessed(qimgOriginal);
    this->thread()->msleep(10);
    //qDebug()<<"processing frames";
}

emit stopProcess();
qDebug()<<"Stop thread";
}
当stop_标志设置为on时,停止while循环并发出

SIGNAL stopProcess()
我在MainWindow类中使用该类,以下是我在构造函数中定义连接的方式:

MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);

video_obj_ = new videoObj();
video_thread_ = new QThread;
this->connect(video_obj_, SIGNAL(imgProcessed(QImage)), SLOT(onImgProcssed(QImage))); \\this is for displaying the image
video_obj_->connect(video_thread_, SIGNAL(started()), SLOT(ProcessFrame()));
video_obj_->moveToThread(video_thread_);
video_thread_->connect(video_obj_, SIGNAL(stopProcess()), SLOT(quit()));
}
上述代码在帧查询中工作良好。我不明白的问题是,如果我在任何MainWiow成员函数中设置了video\u obj\u->stop\u标志,那么videoObj类中的ProcessFrame()应该发出stopProcess()信号并触发video\u thread\u的quit(),然后线程应该完成,也就是说video\u thread\u->finished()是真的

但是,如果我做了如下操作:

connect(video_thread_, SIGNAL(finished()), this, SLOT(onStopProcess())); //onStopProcess() see below

void MainWindow::on_btnStart_clicked()
{
video_obj_->stop_flag = 1;
this->thread()->msleep(10);

video_obj_->capture_.open(ui->lineEditVidoeAddress->text().toStdString());
//... something about videoCapture setting here, not related

video_obj_->capture_.set(CV_CAP_PROP_POS_FRAMES, 0);
video_obj_->stop_flag = 0;
this->thread()->msleep(10);
if(video_thread_->isRunning()){
    qDebug()<<"The thread is still running?!!!";
}
video_thread_->start();
}

void MainWindow::onStopProcess(){
    qDebug()<<"thread is finished";
}
这意味着触发quit()的操作没有完成线程,或者quit()没有被触发

如果我使用:

video_thread_->wait(); //instead of video_thread_->wait(10);
程序将冻结

任何人都可以帮我,这真的让我很困惑,关于这个quit()和finished()。。。
谢谢

因为当调用stop_flag=1时,视频_线程将完成当前函数,该函数为

ProcessFrame
ProcessFramefinish之前,通过emit stopProcess()video\u线程上调用quit

但是,quit不同于terminate,terminate可以随时退出线程(但不安全),quit与事件循环一起工作,如果线程没有eventloop,则quit无效

我猜在qthread执行eventloop中的下一个事件之前,它会检查一些标志,这些标志可以通过quit设置,如果该标志是通过quit设置的,那么它不会执行eventloop中的下一个事件。也可以是将退出事件插入eventloop,eventloop中的下一个事件将退出

stop\u flag=1之后,您调用了video\u thread\u->wait,这将阻止video\u thread\u执行eventloop中的下一个事件,因此退出在超时之前不会生效,但是,打印“not finished?!!!”的下一行会立即执行。如果调用currentThread()->Sleep(一些时间足够了),则视频线程将有时间执行下一个事件并退出,而不是调用video\u thread->wait

您可以阅读QThread的Qt文档,wait与terminate一起用于同步终止线程

=================================================新代码================================

当您这样做时:

myObj->connect(myThread, SIGNAL(started()), SLOT(dowork()));
信号源是myThread,插槽也属于myThread,因为对象“myThread”是在主线程中创建的,因此作为一个对象它生活在主线程中。您可以调用myThread->thread()来查看这一点,它将返回主线程而不是新线程

但是,启动信号是从新线程(即myThread表示的线程)发出的,因此该连接是Qt::QueuedConnection。dowork()被发布在主线程的事件队列中,它将仅在执行主线程eventloop的.exec()之后执行

其他2个connect调用也会发生同样的情况,所有插槽都将在主线程的eventloop中执行

首先调用myThread->start时,新线程会发出start,而dowork会发布到主线程的事件队列中

在调用a.exec()之前,实际上什么都没有发生; 因此,程序将转到cin,然后将stop设置为true,然后打印“线程仍在运行?!!”

Second调用.exec()时,在主线程中执行dowork并打印“开始工作”。没有执行任何操作,因为停止标志已经为真,并且finishwork信号从主线程发出,打印“finish do work”

第三步发出finishwork的最后一步,直接调用退出槽。但是,在新线程真正退出之前,主线程已经完成了eventqueue,因为没有更多的事件发布到主线程。应用程序将在不等待quit()生效的情况下退出

要测试这是否正确,请不要修改任何代码,只需在

emit finishWork();
currentThread()->sleep(1000);
您将看到“thread is finished!”打印出来,因为这为新线程发出finished()留出了时间,并且onfinishThread()将被添加到主线程的事件队列中


顺便说一句,您使用线程的方式看起来像java风格,这不是标准的qt方式。在处理qt线程之前,您可以先阅读。

这不是调度问题

您在代码中执行的操作如下所示:

  • 创建一个线程
  • 然后该线程发出它已启动的信号,运行slot dowork()
  • 开始一个线程
  • 等待用户输入
  • 关于线程正在运行的回声
  • 执行事件循环
  • 在第3点,线程已经在运行,并发出了相应的信号。因为myObj是在主线程中创建的,并且没有移动到任何其他线程(在那里处理事件),所以您的线程现在不做任何其他事情,只是旋转事件循环。同时,告诉您要运行myObj的dowork()的事件将发布在主线程上。最后到了第6步,您开始执行它的事件循环,它发现的第一件事是它需要在myObj上调用dowork()的事件

    使它成为cl
    video_thread_->wait(); //instead of video_thread_->wait(10);
    
    ProcessFrame
    
    myObj->connect(myThread, SIGNAL(started()), SLOT(dowork()));
    
    emit finishWork();
    currentThread()->sleep(1000);