简体   繁体   English

关闭MainWindow后,Qt应用程序仍在运行

[英]Qt Application still running after closing MainWindow

I'm trying to implement a multithreaded app that displays video using the OpenCV libraries (following the example given here ). 我正在尝试实现一个使用OpenCV库显示视频的多线程应用程序(遵循此处给出的示例)。

I create two threads from the GUI thread that successfully terminate when the MainWindow is closed. 我从GUI线程创建两个线程,这些线程在MainWindow关闭时成功终止。 However, the program still keeps on running (I have to use the stop button on the application output panel to close it down). 但是,该程序仍保持运行状态(我必须使用应用程序输出面板上的停止按钮将其关闭)。

Here's my destructor for the 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;
}

The Application Output window returns the following output on both the Debug and Release builds Application Output窗口在Debug和Release版本上均返回以下输出

Capture Thread has exited successfully
Converter Thread has exited successfully

However, the application only quits in Debug mode. 但是,该应用程序仅在调试模式下退出。

From what I have gathered from a few google searches is that the application continues on running IF there is a thread that has not been properly terminated. 从我从一些Google搜索中收集到的信息来看,如果存在未正确终止的线程,则应用程序将继续运行。 Can that be the case here? 可以是这种情况吗? If yes, then how may I know which other thread is also running in the program, so that I may terminate/quit it? 如果是,那么我如何知道程序中还运行了哪个其他线程,以便终止/退出该线程?

Using Qt 5.4 with MSVC 2013 and OpenCV 3.0 beta on Win 8.1 在Win 8.1上将Qt 5.4与MSVC 2013和OpenCV 3.0 beta一起使用

Edit I create my threads in MainWindow constructor 编辑我在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();

Edit 2 : I modified my main.cpp to this 编辑2 :我修改了我的main.cpp

QApplication a(argc, argv);
MainWindow w;
w.show();

int ret;
ret = a.exec();
qDebug() << "QApplication.exec() returns " <<  ret;
return ret;

and I received the following message in the Application output window 我在“应用程序输出”窗口中收到以下消息

QApplication.exec() returns  0
Capture Thread has exited successfully
Converter Thread has exited successfully

which is confusing, since the QApplication should quit after the threads have been stopped. 这很令人困惑,因为QApplication应该在线程停止后退出。 so I moved the thread cleanup to the abouttoQuit() slot. 所以我将线程清理移至abouttoQuit()插槽。 The order of exiting has changed by this modification but the original problem remains. 通过此修改,退出的顺序已更改,但原始问题仍然存在。 (The wrong order could be due to the implementation of the qDebug() function, but thats just me guessing) (错误的顺序可能是由于qDebug()函数的实现,但这仅是我的猜测)

PS I even added captureThread.terminate() and converterThread.terminate() in the destructor but still the results are the same. PS我什captureThread.terminate()在析构函数中添加了captureThread.terminate()converterThread.terminate() ,但结果仍然相同。

Problem 问题

Ok so it turned out to be a memory leak. 好的,原来是内存泄漏。 In the constructor of my MainWindow, I had declared and initialized two instances of converter * and capture * classes. 在MainWindow的构造函数中,我已经声明并初始化了converter *capture *类的两个实例。 However, when the constructor ended its scope, these pointers were never freed. 但是,当构造函数结束其作用域时,这些指针从未被释放。

Solution

Free the memory in the CleanUp() function. 释放CleanUp()函数中的内存。 (The CleanUp() function is connected to the aboutToQuit() slot of the application. To make the pointers accessible to the CleanUp() function, declare them as members of the MainWindow class. CleanUp()函数连接到应用程序的aboutToQuit()插槽。要使指针可用于CleanUp()函数,请将它们声明为MainWindow类的成员。

QMetaObject::invokeMethod(capture, "start");

Looks suspicious. 看起来可疑。 Can you replace it with: 您可以将其替换为:

connect(&captureThread, &QThread::started, capture, &Capture::start);

Also, no need to do thread clean up, because they are members of MainWindow class and will be destroyed with it, remove those two lines: 另外,无需清理线程,因为它们是MainWindow类的成员,并且将随其销毁,因此删除以下两行:

connect(&captureThread, SIGNAL(finished()), &captureThread, SLOT(deleteLater()));
connect(&converterThread, SIGNAL(finished()), &converterThread, SLOT(deleteLater()));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM