用循环(从opencv读取视频)停止QThread的正确方法
The proper way to stop a QThread with a loop (that read a video from opencv)
我想为我的应用程序添加一些多线程(opencv opengl集成),我从这个答案中的结构开始。现在有一个线程可以获取视频帧并将其发送到主窗口,仅此而已。
我试着搜索了一下,但没有什么能让它变得清晰,只会让事情变得更加模糊。
即使我读到一篇文章说不要将QThread
子类化,而是使用moveToThread()
,我也会在某个地方读到另一篇文章(除了一个官方例子)说要这样做
如果我运行应用程序然后关闭它,它就会崩溃。如果我运行应用程序并调用endCapture
,然后重新启动。。它再次崩溃。
感谢您的每一种帮助或评论!
这是VideoThread.h:
#ifndef VIDEOTHREAD_H
#define VIDEOTHREAD_H
#include <QMutex>
#include <QImage>
#include <QThread>
#include <opencv2/core/core.hpp>
#include <opencv2/highgui/highgui.hpp>
class VideoThread : public QThread
{
Q_OBJECT
public:
explicit VideoThread(QObject *parent = 0);
~VideoThread();
protected:
void run();
private:
cv::VideoCapture video;
QMutex m_AbortCaptureLock;
bool m_AbortCapture;
signals:
void sendImage(QImage);
public slots:
void endCapture();
};
#endif // VIDEOTHREAD_H
VideoThread.cpp:
#include "videothread.h"
#include <QDebug>
VideoThread::VideoThread(QObject *parent) :
QThread(parent)
{
qDebug() << "VideoThread > ctor.";
}
VideoThread::~VideoThread()
{
qDebug() << "VideoThread > dtor";
if(video.isOpened()) {
video.release();
qDebug() << "Camera successfully disconnected.";
}
}
void VideoThread::run()
{
m_AbortCapture = false;
video = cv::VideoCapture(0);
qDebug() << "VideoThread::run..";
while(true)
{
m_AbortCaptureLock.lock();
if (m_AbortCapture) {
qDebug() << "VideoThread::run > abort capture..";
break;
}
m_AbortCaptureLock.unlock();
cv::Mat cvFrame;
video >> cvFrame;
if(cvFrame.empty()) continue;
// convert the Mat to a QImage
QImage qtFrame(cvFrame.data, cvFrame.size().width, cvFrame.size().height, cvFrame.step, QImage::Format_RGB888);
qtFrame = qtFrame.rgbSwapped();
// queue the image to the gui
emit sendImage(qtFrame);
msleep(20);
}
}
void VideoThread::endCapture()
{
qDebug() << "VideoThread::endCapture()";
m_AbortCaptureLock.lock();
m_AbortCapture = true;
m_AbortCaptureLock.unlock();
}
这里是主要的:
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "opencv_glwidget.h"
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
OpenCV_GLWidget *w = new OpenCV_GLWidget();
w->setParent(this->centralWidget());
connect(ui->checkBox, SIGNAL(toggled(bool)),
this, SLOT(toggle(bool)));
ui->checkBox->toggle();
connect(&thread, SIGNAL(sendImage(QImage)),
w, SLOT(renderImage(QImage)));
thread.start();
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::toggle(bool n)
{
if(n) {
thread.start();
} else {
thread.endCapture();
}
}
不要将QThread
子类化。创建包含插槽的QObject
的子类。这个槽应该包含无限循环的一次迭代的代码(循环应该被删除)。创建一个QThread
对象,并使用moveToThread
将对象移动到此线程。创建一个QTimer
,将其连接到对象的插槽,并以所需的间隔(20毫秒)启动。由于对象属于其他线程,因此它的槽将在该线程中定期执行。当您想停止执行时,在线程上调用quit()
和wait()
。它将停止执行。
相关文章:
- 遇到新行时,有没有办法停止istream_iterator
- 线程之间的布尔停止信号
- 如何正确停止g_main_loop_run
- 如何监控QThread
- 当用户键入分隔符时,停止getline()输入
- MPI突然停止了对多个核心的操作
- 停止cmake target_link_libraries将插件中静态库的两个对象文件链接到静态库本身
- 当我在其中一个线程执行中(在activemq-cpp中)捕获到特定值时,我如何终止/停止所有其他线程
- 如何使用隔离>终止执行来停止所有线程
- 我可以使用什么来停止循环而不是"返回 0"?
- gdb错误:Backtrace已停止:上一帧与此帧相同(堆栈已损坏?)
- 如何正确停止运行非循环QThread?
- 如何使用无限循环停止Qthread
- 如何在 QT 中停止 qThread
- 停止线程的方法是什么(当我直接从Qthread继承时)
- 如何在qthread上创建QTCPSERVER,然后从主线程中将其停止
- g_main_loop_run阻塞Qthread并且不允许停止视频
- 用循环(从opencv读取视频)停止QThread的正确方法
- 如何停止运行永久阻塞循环的QThread
- 停止QThread工作进程处理即将删除的资源的正确方法是什么