- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我是 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() 先运行,但它根本不起作用,输出是
所以我真的很困惑 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/
我目前正在为 Cocoa/Objective-C 项目编写一个脚本来完全自动化我的编译-运行-调试过程。 我的最后一行代码是: lldb -f Build/MyApp.app -o "run" 这实际
我有一个带有登录屏幕的脚本,如果按下取消按钮,我想完全退出该应用程序。我尝试了 3 种方法: 系统退出() QApplication.quit() QCoreApplication.instance(
我有一个 Flash 应用程序,可以重定向到另一个页面。我很乐意捕获任何其他窗口卸载事件(单击链接/提交表单)并警告用户他们将丢失 Flash 应用程序中的进度。 但是,我找不到任何方法来判断 URL
我正在尝试在 Ubuntu 上用 Python 编写一个简单的程序,它将在播放视频完成后关闭/退出/退出 VLC Player。 能否请您指导我应该在我的程序中添加什么以获得我需要的结果。 impor
我在 Lynda.com 上学习 PHP 2 视频时遇到了一个问题,因为讲师似乎忽略了告诉我们他在视频中执行的步骤之一。我在这里上传了相关视频http://www.youtube.com/watch?
某天在群内有同学问到,在python下我用input或者raw_input都得输入完后回车才能获取到输入的值,那如何实现任意键退出暂停等功能呢,我当时也没有多想,因为接触python时间也不算长,主
我按顺序调用了几个函数(我无法编辑),但有些函数会重定向用户,所以我永远不会进入下一个函数。 我正在调用一个第三方函数,它调用了我能够阻止的 wp_redirect(),但是下一行是 exit;我不知
终止/退出主函数的 D 方式是什么? import std.stdio; import core.thread; void main() { int i; while (i <= 5)
我正在申请写作。用户可以打开应用程序、写一些文本、保存他们的工作等。 我试图做到这一点,以便点击 window close按钮将提示用户 (a) 保存他们的工作(如有必要)或 (b) 退出。 我正在尝
我正在通过在 repl 中检查别人的代码来玩弄它。 它不断调用 System/exit,这导致我的 repl 崩溃。这真是令人气愤。 在我有权访问的所有代码中,我都模拟了调用。 但它也会调用一些我没有
我正在使用 subprocess执行mimic的模块程序(指定 here )。下面的代码成功地读取了一些文本并写入了一个 mp3 文件。 import subprocess proc = subpro
退出 .then 范围后数组上的值被清除 在下面的代码中tableValues1.length 给我正确的长度,直到它位于每个循环内当它退出时,作用域数组长度为零。 请谁能帮我解决这个问题 - 谢谢
我正在尝试为 s3cmd 编写一个 docker 镜像。当我通过 docker-compose 运行从 Dockerfile 构建的图像时,容器在 docker compose run 命令之前退出。
这个问题已经有答案了: 已关闭12 年前。 Possible Duplicate: Quitting an application - is that frowned upon? 我编写了一个 And
我遇到 Selenium WebDriver 仅执行一次后退出 for 循环的问题。据推测,这是获取内容和在加载页面之前启动循环的问题。是否有可能让 webdriver 等待页面加载? List al
#include #include #include #include "Player.h" using namespace std; void PlayerMenu(); int main()
class Test{ public static void main(String args[]) { Patron list[] = new PatronData(
我正在做一些作业,遇到了这个问题。 Write a program that reads several lines of text and prints a table indicating the
我正在用 C 创建一个简单的 Linux 命令 shell。我无法理解我的代码在哪里出现问题。 “commands”是我希望作为一个父进程的子进程同时执行的 Linux 命令字符串列表。当所有执行完成
我的控制台应用程序有点问题。应用程序应该从用户那里获取数字并将它们添加到列表中,但是如果输入是“c”,它应该关闭。我不知道如何在不使用 Scanner.nextLine() 挂起应用程序并退出循环的情
我是一名优秀的程序员,十分优秀!