我正在尝试实现一个使用OpenCV库显示视频的多线程应用程序(遵循给定here的示例)。
我从GUI线程创建两个线程,在MainWindow关闭时成功终止。但是,程序仍然在运行(我必须使用应用程序输出面板上的停止按钮将其关闭)。
这是我对MainWindow的析构函数
MainWindow::~MainWindow()
{
captureThread.quit();
converterThread.quit();
if (captureThread.wait())
qDebug() << "Capture Thread has exited successfully";
if (converterThread.wait())
qDebug() << "Converter Thread has exited successfully";
delete ui;
}
“应用程序输出”窗口在“调试”和“发布版本”
上返回以下输出Capture Thread has exited successfully
Converter Thread has exited successfully
但是,应用程序仅在调试模式下退出。
从我从一些谷歌搜索中收集到的是,如果有一个未正确终止的线程,应用程序将继续运行。可以这样吗?如果是,那我怎么知道哪个其他线程也在程序中运行,以便我可以终止/退出呢?
在Win 8.1上使用Qt 5.4与MSVC 2013和OpenCV 3.0 beta
修改 我在MainWindow构造函数
中创建我的线程MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
// registers the type cv::Mat. After a type is registered, one can create/destroy objects at runtime
qRegisterMetaType<Mat>();
// Initializing class' instance
Capture* capture = new Capture;
Converter* converter = new Converter;
ui->labelFrame->setAttribute(Qt::WA_OpaquePaintEvent);
converter->setProcessAll(false);
capture->moveToThread(&captureThread);
converter->moveToThread(&converterThread);
converter->connect(capture, SIGNAL(matReady(Mat)), converter, SLOT(processFrame(Mat)));
this->connect(converter, SIGNAL(imageReady(QImage)), this, SLOT(setImage(QImage)));
// thread clean up
connect(&captureThread, SIGNAL(finished()), &captureThread, SLOT(deleteLater()));
connect(&converterThread, SIGNAL(finished()), &converterThread, SLOT(deleteLater()));
QObject::connect(capture, &Capture::started,
[](){ qDebug() << "capture started"; });
QMetaObject::invokeMethod(capture, "start");
captureThread.start();
converterThread.start();
编辑2 :我将main.cpp修改为此
QApplication a(argc, argv);
MainWindow w;
w.show();
int ret;
ret = a.exec();
qDebug() << "QApplication.exec() returns " << ret;
return ret;
我在应用程序输出窗口中收到以下消息
QApplication.exec() returns 0
Capture Thread has exited successfully
Converter Thread has exited successfully
这令人困惑,因为QApplication应该在线程停止后退出。所以我将线程清理移动到abouttoQuit()
槽。退出的顺序已经通过此修改而改变,但原始问题仍然存在。 (错误的顺序可能是由于qDebug()函数的实现,但这只是我的猜测)
PS 我甚至在析构函数中添加了captureThread.terminate()
和converterThread.terminate()
,但结果仍然相同。
答案 0 :(得分:1)
<强>问题强>
好的,结果是内存泄漏。在我的MainWindow的构造函数中,我声明并初始化了两个converter *
和capture *
类的实例。但是,当构造函数结束其范围时,这些指针从未被释放。
<强>解决方案强>
释放CleanUp()
功能中的内存。 (CleanUp()
函数连接到应用程序的aboutToQuit()
槽。要使指针可以访问CleanUp()函数,请将它们声明为MainWindow
类的成员。
答案 1 :(得分:0)
QMetaObject::invokeMethod(capture, "start");
看起来很可疑。你可以用以下代码替换它:
connect(&captureThread, &QThread::started, capture, &Capture::start);
此外,不需要进行线程清理,因为它们是MainWindow类的成员并将随之被销毁,删除这两行:
connect(&captureThread, SIGNAL(finished()), &captureThread, SLOT(deleteLater()));
connect(&converterThread, SIGNAL(finished()), &converterThread, SLOT(deleteLater()));