I am trying to create a thread for a Scanner class which handles all the events for this particular class, thereby freeing the GUI thread. I have an exit button on my GUI which simply calls qApp->quit() to exit the application, but I am not sure how to deal with the thread in my Scanner class. I am seeing the following errors in the debug log when the application is exited.
QThread::wait: Thread tried to wait on itself
QThread::wait: Thread tried to wait on itself
QThread: Destroyed while thread is still running
In Scanner.cpp (Omitted other functions)
Scanner::Scanner() :
{
this->moveToThread(&m_thread);
connect(&m_thread, &QThread::finished, this, &QObject::deleteLater);
connect(this, SIGNAL(StartEnroll()), this, SLOT(StartEnrollment()));
m_thread.start();
}
Scanner::~Scanner()
{
m_thread.quit(); // Not sure if this is the correct
m_thread.wait();
}
In main Window.cpp (Omitted other functions)
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
connect(ui->ExitButton, SIGNAL(released()), this, SLOT(Quit()));
connect(&m_scanner, SIGNAL(FinishedEnroll(bool)), this, SLOT(EnrollDone(bool)));
}
void MainWindow::Quit()
{
close();
qApp->quit();
}
Any pointers on how to quit safely quit the application in a multi-threaded application.
You need to let the Scanner
class know that the application is exiting.
Add the following line to the constructor of MainWindow
connect(qApp, SIGNAL(aboutToQuit()), &m_scanner, SLOT(deleteLater()));
UPDATE:
connect(&m_thread, &QThread::finished, this, &QObject::deleteLater);
Should not be in the constructor of Scanner
and
m_thread.quit();
m_thread.wait();
should not be in the destructor of Scanner
In fact, m_thread
should not be part of Scanner
in any way. The QThread
class does not represent a thread, it is a thread manager and should be owned and controlled from the thread where it was created.
There are a number of methods of using threads in Qt, many not documented very well. If you want to use the
workerObject->moveToThread(&thread);
thread.start();
way of using threads, then m_thread
should be a member of MainWindow
class and these function calls should be made in it's constructor.
Thanks for clarifying and for the solutions posted above. Here is what I did based on what was posted before.
ScannerThread.h
#include <QThread>
class ScannerThread : public QThread
{
public:
ScannerThread();
~ScannerThread();
};
ScannerThread.cpp
#include "scannerthread.h"
ScannerThread::ScannerThread()
{
connect(this, &QThread::finished, this, &QObject::deleteLater);
}
ScannerThread::~ScannerThread()
{
quit();
wait();
}
In MainWindow.h
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void Quit();
private:
Ui::MainWindow *ui;
Scanner m_scanner;
ScannerThread m_scannerThread;
};
In MainWindow.cpp (Omitting other functions)
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
m_scanner.moveToThread(&m_scannerThread);
m_scannerThread.start();
connect(ui->ExitButton, SIGNAL(released()), this, SLOT(Quit()));
connect(qApp, SIGNAL(aboutToQuit()), &m_scanner, SLOT(deleteLater()));
}
void MainWindow::Quit()
{
close();
qApp->quit();
}
This seemed to work fine for me. If you see any errors please correct, and thanks for helping with this.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With