gpt4 book ai didi

qt - QThread什么时候退出()或完成()?

转载 作者:行者123 更新时间:2023-12-05 02:24:17 25 4
gpt4 key购买 nike

我是 Qt 新手,只想在 Qt GUI 中显示视频。除了处理 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!";
}

然后是主函数

#include <QCoreApplication>
#include <QThread>

#include <iostream>
#include <windows.h>

#include "myobject.h"

using namespace std;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);

myObject* myObj = new myObject();
QThread* myThread = new QThread;

myThread->connect(myObj, SIGNAL(finishWork()), SLOT(quit()));
myObj->connect(myThread, SIGNAL(started()), SLOT(dowork()));
myObj->connect(myThread, SIGNAL(finished()), SLOT(onfinishThread()));
myObj->moveToThread(myThread);

myObj->stop = false;

myThread->start();

cout<<"Press ENTER to continue....."<<endl<<endl;
cin.ignore(1);

myObj->stop = true;
Sleep(10);

if(myThread->isRunning()){
qDebug()<<"The thread is still running?!!!";
}

/*
myObj->stop = false;
Sleep(1000);
myThread->start();
myObj->stop = true;
*/

myObj->deleteLater();
myThread->deleteLater();
return a.exec();
}

如您所见,我什至使用 cin 尝试让 dowork() 先运行,但它根本不起作用,输出是

output

所以我真的很困惑 QThread 的调度是如何工作的......

此外,如果您取消注释该部分

/*
myObj->stop = false;
Sleep(1000);
myThread->start();
myObj->stop = true;
*/

输出完全一样!打印后只停留一段时间

The thread is still running?!!!

谁能帮我解决这个问题?非常感谢。您可以简单地复制所有代码并自行测试。


------------------------原题,不好解释,请忽略....-- --------------------------------------

我制作了一个只有一个函数来查询帧的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";
}

基本上上面的代码只是查询帧,每当有一个发出时

SIGNAL imgProcessed(qimgOriginal)

每当 stop_flag 设置为 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_obj_->stop_flag,videoObj 类中的 ProcessFrame() 应该发出 stopProcess() 信号并触发 video_thread_ 的 quit(),然后线程应该完成,即 video_thread_->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";
}

它会给我输出:

Stop thread 
The thread is still running?!!!
thread is finished

这意味着触发 quit() 并没有结束线程,或者 quit() 还没有被触发。

如果我使用:

video_thread_->wait(); //instead of video_thread_->wait(10);

程序将卡住。

有没有人能帮我解决这个问题,我真的很困惑这个 quit() 和 finished()...谢谢!

最佳答案

因为当您调用 stop_flag=1 时,video_thread_ 完成当前函数,即

ProcessFrame

ProcessFrame 完成之前,通过 emit stopProcess()video_thread_ 上调用 quit。

但是quit和terminate不同,terminate可以随时退出线程(但是不安全),quit和event loop配合使用,如果线程没有eventloop,quit没有作用。

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

stop_flag = 1之后,你调用了video_thread_->wait,这将阻止video_thread_执行事件循环中的下一个事件,因此退出不会生效然而,在超时之前,打印“未完成?!!!”的下一行立即执行。如果您调用 currentThread()->Sleep(some_enough_time) 而不是调用 video_thread->wait,那么 video_thread_ 将有时间执行下一个事件并退出。

QThread的Qt文档可以看看,wait和terminate一起使用来同步终止一个线程。

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

当你这样做时:

myObj->connect(myThread, SIGNAL(started()), SLOT(dowork()));

信号源是myThread,slot也属于myThread,因为对象“myThread”是在主线程中创建的,所以作为对象存在于主线程中。你可以调用 myThread->thread() 看看这个,它会返回主线程而不是新线程。

但是,启动信号是从新线程发出的,即 myThread 代表的线程,因此连接是 Qt::QueuedConnection。 dowork()被放入主线程的事件队列中,只有在执行主线程eventloop的a.exec()之后才会执行。

同样的事情发生在其他 2 个连接调用上,所有的槽都将在主线程的事件循环中执行。

首先当 myThread->start 被调用时,开始从新线程发出,dowork 被发布到主线程的事件队列中。

在调用 a.exec() 之前什么都没有发生;所以程序会继续执行 cin 然后将 stop 设置为 true,然后打印“Thread is still running?!!”。

其次 调用a.exec()时,dowork在主线程中执行,并打印“start work”。什么都没做,因为停止标志已经为真,并且从主线程发出完成信号,打印“finish do work”;

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

要测试这是真的,不要修改任何代码,只需在

之后添加
emit finishWork();
currentThread()->sleep(1000);

你会看到“线程结束了!”打印,因为这为新线程腾出时间来发出 finished(),并且 onfinishThread() 将被添加到主线程的事件队列中。

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

关于qt - QThread什么时候退出()或完成()?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13966284/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com