QTimer in multithreaded application - c++

Okay, so I've completely lost in QTimer. The problem is: I have multithreaded application, and I need to do some work on QTimer's timeout. I've done like this:
QTimer* timer = new QTimer();
timer->setSingleShot(true);
connect(timer, SIGNAL(timeout()), someObject, SLOT(work()));
And this did not work. Sometimes, work() was not called at all, sometimes it was called when I closed program, and sometimes all seemed normal.
So I've come to idea that timer needs thread. To provide MCV example :
class Tester : public QObject
{
Q_OBJECT
public:
Tester(QObject* par = 0) : QObject(par)
{
}
public slots:
void greet()
{
qDebug()<<"hello";
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer* timer1 = new QTimer();
QThread* thread = new QThread();
Tester* tester = new Tester();
timer1->setInterval(500);
timer1->setSingleShot(false);
timer1->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), timer1, SLOT(start()));
QObject::connect(timer1, SIGNAL(timeout()), tester, SLOT(greet()));
QObject::connect(timer1, SIGNAL(timeout()), timer1, SLOT(deleteLater()));
QObject::connect(timer1, SIGNAL(destroyed()), thread, SLOT(quit()));
thread->start();
thread->wait();
delete thread;
delete tester;
return a.exec();
}
And this example does nothing. It does not greet me, so timeout is not called, and it does not end, so thread is not stopped. So questions are:
1. What is wrong with this code?
2. How properly use QTimer in multithreaded environment?

Just calling QTimer::setInterval doesn't start the QTimer. It just sets the interval in which the QTimer::timeout signal is emitted. You didn't start the QTimer. Use QTimer::start.
I think you're doing several mistakes here. You need to move the timer to thread after all the connections are made. Not sure how safe would be to start the timer when the thread starts because at that point, the timer would be in one thread and the thread object would be in another thread. QTimer must be started from the same thread in which it was created. The QThread object is just a thread handler and it lives in the thread in which was created. See the modifications I made to your example:
#include <QCoreApplication>
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <QObject>
//#include "tester.h"
class Tester : public QObject
{
Q_OBJECT
public:
Tester(QObject* par = 0) : QObject(par)
{
}
public slots:
void greet()
{
qDebug()<<"hello";
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
QTimer* timer1 = new QTimer();
QThread* thread = new QThread();
Tester* tester = new Tester();
timer1->setInterval(500);
timer1->setSingleShot(false);
timer1->start();
QObject::connect(timer1, SIGNAL(timeout()), tester, SLOT(greet()));
timer1->moveToThread(thread);
thread->start();
return a.exec();
}
It's not the safest/best fix(memory leaks and other) but it is, i hope, an example on which you can build.
This would be in my opinion the right and without memory leaks way to use a QTimer in another QThread:
handler.h
#ifndef HANDLER_H
#define HANDLER_H
#include <QObject>
class QTimer;
class QThread;
class Tester;
class Handler : public QObject
{
Q_OBJECT
public:
explicit Handler(QObject *parent = 0);
~Handler();
void exec();
private:
QTimer* timer;
QThread* thread;
Tester* tester;
};
#endif // HANDLER_H
handler.cpp
#include "handler.h"
#include "tester.h"
#include <QThread>
#include <QDebug>
#include <QTimer>
#include <QObject>
#include <QCoreApplication>
Handler::Handler(QObject *parent) :
QObject(parent)
{
timer = new QTimer;
thread = new QThread(this);
tester = new Tester(this);
timer->setInterval(500);
timer->setSingleShot(false);
QObject::connect(timer, SIGNAL(timeout()), tester, SLOT(greet()));
QObject::connect(thread, SIGNAL(destroyed()), timer, SLOT(deleteLater()));
}
Handler::~Handler()
{
thread->wait();
}
void Handler::exec()
{
timer->start();
timer->moveToThread(thread);
thread->start();
}
tester.h
#ifndef TESTER_H
#define TESTER_H
#include <QObject>
class Tester : public QObject
{
Q_OBJECT
public:
Tester(QObject* par = 0);
public slots:
void greet();
};
#endif // TESTER_H
tester.cpp
#include "tester.h"
#include <QDebug>
Tester::Tester(QObject *parent) :
QObject(parent)
{
}
void Tester::greet()
{
qDebug()<<"hello";
}
main.cpp
#include <QCoreApplication>
#include "handler.h"
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Handler handler;
handler.exec();
return a.exec();
}

Related

Qt multi-thread with GUI

I cannot produce a very simple example to getting start with Qt multi-thread. I read a lot of posts and tutorials but still it doesn't work.
Goal
Have a background worker independent from the GUI. Oh, wow...
What I did
A simple example:
create the Engine class
that shows a QMainWindow
and starts a QTimer that prints a number
But if you left-click the title bar of the GUI, keeping pressed the mouse button (i.e. on the minimize button) the counter will stop! Even if it was created in a non-GUI environment and it was moved in another thread!
Why?
main.cpp
#include "engine.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Engine e;
return a.exec();
}
engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QThread>
#include <QTimer>
#include "mainwindow.h"
class Engine : public QObject
{
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
MainWindow mainWindow;
QThread *thread;
QTimer *timer;
private slots:
void foo();
};
#endif // ENGINE_H
engine.c
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
{
thread = new QThread(this);
timer = new QTimer();
timer->setInterval(100);
connect(timer, &QTimer::timeout, this, &Engine::foo);
connect(thread, &QThread::started, timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
timer->moveToThread(thread);
thread->start();
mainWindow.show();
}
void Engine::foo()
{
static int i;
qDebug() << ++i;
}
The QMainWindow contains no code.
Basically, Qt has one thread dealing with the GUI (typically the main thread). Any objects specific to this thread will be blocked by GUI work. You need to keep the GUI outside of your interacting partners.
To be more specific, your Engine object resides in the GUI/main thread. Even while your timer is sent to a worker thread, its signals are dispatched to the slot foo() in the main thread.
You need to de-mangle Engine and the main window such that Engine can reside in its own thread and process signals while the GUI is blocking.
Looks like you moved QTimer instance to your custom thread, but you didnt move Engine instance to this thread, therefore, foo slot of Engine class will be executed in main thread.
I can suggest you using additional helping QObject-derived class instance within Engine class and move it to your new thread in Engine constructor.
With following changes solution works fine even with minimize button pressed (I've commented places where i added or changed anything. Also added new QObject-derived class EngineWorker):
Engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QThread>
#include <QTimer>
#include "mainwindow.h"
#include "engineworker.h"
class Engine : public QObject
{
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
MainWindow mainWindow;
QThread *thread;
QTimer *timer;
//additional QObject-derived class
EngineWorker *worker;
private slots:
void foo();
};
#endif // ENGINE_H
Engine.cpp
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
{
thread = new QThread(this);
timer = new QTimer();
//Creating instance of Engine worker
worker = new EngineWorker();
timer->setInterval(100);
//Connecting Engine worker' foo slot to timer
connect(timer, &QTimer::timeout, worker, &EngineWorker::foo);
connect(thread, &QThread::started, timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
timer->moveToThread(thread);
//Moving worker to custom thread
worker->moveToThread(thread);
thread->start();
mainWindow.show();
}
void Engine::foo()
{
static int i;
qDebug() << ++i;
}
EngineWorker.h
#ifndef ENGINEWORKER_H
#define ENGINEWORKER_H
#include <QObject>
#include <QDebug>
class EngineWorker : public QObject
{
Q_OBJECT
public:
explicit EngineWorker(QObject *parent = 0);
signals:
public slots:
void foo();
};
#endif // ENGINEWORKER_H
EngineWorker.cpp
#include "engineworker.h"
EngineWorker::EngineWorker(QObject *parent) : QObject(parent)
{
}
//foo slot of EngineWorker class
void EngineWorker::foo()
{
static int j;
qDebug() <<"Worker: "<< ++j;
}

Qt - SIGNAL & SLOT are not updating my QLabel in mainwindow from a worker class

I applied an C++ example of working with threads in Qt 5.7. All things are good except two things:
1- I used Signal & Slot to update my label in the main form. the problem is that is no effect. Really, I don't know where is the issue.
2- The loop works fine, but when I exit my program I see (throught the "Application Output") that the loop still work (I think that's related with the started thread).
This my little example:
mainwindow.h
#ifndef MAINWINDOW_H
#define MAINWINDOW_H
#include <QMainWindow>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_pushButton_clicked();
void updateLabelText(const QString TheString);
private:
Ui::MainWindow *ui;
};
#endif // MAINWINDOW_H
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
//#include <QDebug>
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QThread *workerThread = new QThread;
Worker *worker = new Worker;
worker->moveToThread(workerThread);
connect(worker, SIGNAL(sendText(const QString)), this, SLOT(updateLabelText(QString)));
workerThread->start();
}
void MainWindow::updateLabelText(const QString TheString)
{
ui->label->setText(TheString);
}
worker.h
#ifndef WORKER_H
#define WORKER_H
#include <QObject>
class Worker : public QObject
{
Q_OBJECT
public:
explicit Worker();
public slots:
void doWork();
signals:
void sendText(const QString);
};
#endif // WORKER_H
worker.cpp
#include "worker.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QThread>
#include <QMessageBox>
#include <QApplication>
Worker::Worker()
{
doWork();
}
void Worker::doWork()
{
for (int i = 0; i<999999; i++) {
emit sendText(QString::number(i));
qDebug() << "The number is : " + QString::number(i);
qApp->processEvents();
//QThread::msleep(5);
}
}
How can I fix this?
Thanks.
In your code, doWork() function is called from the Worker's constructor, the constructor is invoked in the main thread (that is done in the line Worker* worker= new Worker;).
Of course, that is not what you meant to do, since it will cause the main thread to execute the for loop in doWork() before even reaching into the connect call.
Instead of calling doWork() from the Worker's constructor, you should connect the thread's started() signal to doWork() slot, then call thread->start() after moving the Worker object to the new thread. This will leverage Qt cross-thread signals to invoke doWork() in the new thread as soon as it starts.
Here is how your code should look like:
#include <QtWidgets>
//QThread wrapper for safe destruction
//see http://stackoverflow.com/a/19666329
class Thread : public QThread{
using QThread::run; //final
public:
Thread(QObject* parent= nullptr): QThread(parent){}
~Thread(){ quit(); wait();}
};
class Worker : public QObject{
Q_OBJECT
public:
explicit Worker(QObject* parent= nullptr): QObject(parent){}
~Worker()= default;
Q_SIGNAL void sendText(QString text);
Q_SIGNAL void workFinished();
Q_SLOT void doWork(){
for (int i = 0; i<1000; i++) {
emit sendText(QString::number(i));
QThread::msleep(5);
}
emit workFinished();
}
};
class Widget : public QWidget{
Q_OBJECT
public:
explicit Widget(QWidget* parent= nullptr): QWidget(parent){
layout.addWidget(&buttonWork);
layout.addWidget(&label);
connect(&buttonWork, &QPushButton::clicked,
this, &Widget::buttonWorkClicked);
}
~Widget()= default;
Q_SLOT void buttonWorkClicked(){
Thread* thread= new Thread(this);
Worker* worker= new Worker;
worker->moveToThread(thread);
//invoke doWork as soon as the thread is started
connect(thread, &QThread::started, worker, &Worker::doWork);
connect(worker, &Worker::sendText, this, &Widget::updateLabelText);
//quit the thread when work is finished
connect(worker, &Worker::workFinished, thread, &QThread::quit);
//destroy thread and worker object when work is finished
connect(thread, &QThread::finished, thread, &QObject::deleteLater);
connect(thread, &QThread::finished, worker, &QObject::deleteLater);
//start the thread
thread->start();
}
Q_SLOT void updateLabelText(QString text){
label.setText(text);
}
private:
QVBoxLayout layout{this};
QPushButton buttonWork{"Work"};
QLabel label{"No work yet"};
};
int main(int argc, char* argv[]){
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"
I solved my problem by following the comment of Mr #Mike.
Simply, I removed the doWork() function from the instructor. Then, I added new connection between the thread's started() SIGNAL and worker's doWork() SLOT.
So thes are the changes:
mainwindow.cpp
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "worker.h"
#include <QThread>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_clicked()
{
QThread *workerThread = new QThread;
Worker *worker = new Worker;
connect(workerThread, SIGNAL(started()), worker, SLOT(doWork()),Qt::QueuedConnection);
connect(worker, SIGNAL(sendText(const QString)), this, SLOT(updateLabelText(const QString)),Qt::QueuedConnection);
worker->moveToThread(workerThread);
workerThread->start();
}
void MainWindow::updateLabelText(const QString TheString)
{
ui->label->setText(TheString);
}
worker.cpp
#include "worker.h"
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>
#include <QThread>
#include <QMessageBox>
#include <QApplication>
Worker::Worker()
{
doWork();
}
void Worker::doWork()
{
for (int i = 0; i<999999; i++) {
emit sendText(QString::number(i));
qDebug() << "The number is : " + QString::number(i);
qApp->processEvents();
QThread::msleep(5);
}
}

Qt: Multithreading connect does not work

I want to connect two threads. One Thread is the Mainthread of my application the other on is a workerthread. I have based my code on the following example doc.qt.io/qt-5/. For me it does not work completely. I am sending a QString to my WorkerThread (this works) and want to send it afterwards back to the MainThread (does not work). Before asking why I am doing this that's just a very simple example. The real Code is much more complex but I have exactly the same problem. If those example would run I am very sure that the complex one would work too. Here the code:
Main.cpp
#include "Controller_C.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Controller_C Controller;
Controller.SendData("Hello World!");
return a.exec();
}
Controller_C.cpp
#include "Controller_C.h"
#include <qmessagebox.h>
Controller_C::Controller_C(QWidget *parent)
: QMainWindow(parent),
Worker(new Worker_C())
{
ui.setupUi(this);
Worker->moveToThread(&WorkerThread);
connect(&WorkerThread, SIGNAL(started()), this, SLOT(ThreadStarted()));
connect(this, SIGNAL(SendToWorker(QString)), Worker, SLOT(DoWork(QString)));
connect(Worker, SIGNAL(SendToController()), this, SLOT(ReceiveData()));
WorkerThread.start();
}
Controller_C::~Controller_C()
{
}
void Controller_C::SendData(QString aString)
{
QThread* Controller = QThread::currentThread();
QMessageBox::information(this, "Info", QString("We have send the following to the Worker Thread: %1").arg(aString));
emit SendToWorker(aString);
}
void Controller_C::ReceiveData(QString aString)
{
QThread* Controller = QThread::currentThread();
QMessageBox::information(this, "Info", QString("The Controller received the following: %1").arg(aString));
}
Controller_C.h
#ifndef CONTROLLER_C_H
#define CONTROLLER_C_H
#include <QtWidgets/QMainWindow>
#include "ui_Controller_C.h"
#include "Worker_C.h"
#include <qthread.h>
class Controller_C : public QMainWindow
{
Q_OBJECT
public:
Controller_C(QWidget *parent = 0);
~Controller_C();
void SendData(QString aString);
private:
Ui::Qt_TestEnvironmentClass ui;
Worker_C* Worker;
QThread WorkerThread;
signals:
void SendToWorker(QString);
public slots:
void ReceiveData(QString aString);
};
#endif // CONTROLLER_C_H
Worker_C.cpp
#include "Worker_C.h"
#include <qmessagebox.h>
#include <qthread.h>
Worker_C::Worker_C()
{
}
Worker_C::~Worker_C()
{
}
void Worker_C::DoWork(QString aString)
{
QThread* Worker = QThread::currentThread();
emit SendToController(aString);
}
Worker_C.h
#ifndef WORKER_C_H
#define WORKER_C_H
#include <QObject>
class Worker_C : public QObject
{
Q_OBJECT
public:
Worker_C();
~Worker_C();
public slots:
void DoWork(QString aString);
signals:
void SendToController(QString);
};
#endif // WORKER_C_H
Thanks for your help.
Like the way you definied the Slot/Signal in your header:
void ReceiveData(QString aString);
void SendToController(QString);
You should also use them like this in your connect:
connect(Worker, SIGNAL(SendToController(QString)), this, SLOT(ReceiveData(QString)));`

custom class with its own QTimer and QThread

I would like to create a class that has its own QTimer and QThread for some projects for Robot's sensors. After some searching, this is what I came up with
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QObject>
#include <QDebug>
//#####################( Robot Class )#########################3
class Robot : public QObject
{
public:
Robot(QObject *parent = 0);
~Robot();
private:
QTimer *mQTimer;
QThread *mQThread;
public slots:
void update();
};
Robot::Robot(QObject *parent)
: QObject(parent)
{
mQTimer = new QTimer(0);
mQThread = new QThread(this);
mQTimer->setInterval(1);
mQTimer->moveToThread(mQThread);
connect(mQTimer, SIGNAL(timeout()), this, SLOT(update()));
connect(mQThread, SIGNAL(started()), mQTimer, SLOT(start()));
mQThread->start();
//mQTimer->start();
}
Robot::~Robot()
{
delete mQTimer;
delete mQThread;
}
void Robot::update()
{
qDebug() << "Robot is updating ...";
}
//##################( Main )###########################
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Robot *myRobot = new Robot(0);
return a.exec();
}
I'm getting this error
QObject::connect: No such slot QObject::update() in ..\untitled1\main.cpp:34
QObject::connect: No such slot QObject::update() in ..\untitled1\main.cpp:34
You are missing the Q_OBJECT macro in your class also try to avoid naming the methods like that because you can mix it with Qt methods names. Also make additional header and cpp file for each class you create in this case make robtot.h and robot.cpp.
class Robot : public QObject
{
Q_OBJECT
public:
Robot(QObject *parent = 0);
~Robot();
...
The below works for me. You forgot the Q_OBJECT macro and to include the moc output that defines the static metadata for Robot.
There's of course no point to this code, since the Robot::update slot will execute in the main thread.
Your code has two threads: the main thread, where the Robot object lives, and the robot.mThread, where the timer lives. The timer will time out in the mThread, and will queue a slot call on the main thread. That slot call will end up invoking robot.update with a.exec on the stack.
Note that there's no need to explicitly have the timer and the thread allocated on the heap using new. They should be direct members of Robot, or of its PIMPL.
main.cpp
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QDebug>
class Robot : public QObject
{
Q_OBJECT
QTimer mTimer;
QThread mThread;
public:
Robot(QObject *parent = 0) : QObject(parent) {
connect(&mTimer, &QTimer::timeout, this, &Robot::update);;
mTimer.start(1000);
mTimer.moveToThread(&mThread);
mThread.start();
}
Q_SLOT void update() {
qDebug() << "updating";
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Robot robot;
return a.exec();
}
#include "main.moc"
It would make more sense to move the entire robot to its own thread. Note that when you do that, you need to set parentage on all objects owned by robot, so that they all switch threads along with the Robot object.
The Thread class fixes the long standing usability bug of QThread - it turns it into a truly RAII class that can be safely destructed at any time.
main.cpp
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
#include <QDebug>
class Thread : public QThread {
using QThread::run;
public:
~Thread() { quit(); wait(); }
};
class Robot : public QObject
{
Q_OBJECT
QTimer mTimer;
int mCounter;
public:
Robot(QObject *parent = 0) : QObject(parent), mTimer(this), mCounter(0) {
connect(&mTimer, &QTimer::timeout, this, &Robot::update);;
mTimer.start(1000);
}
Q_SLOT void update() {
qDebug() << "updating";
if (++mCounter > 5) qApp->exit();
}
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Robot robot;
Thread thread;
robot.moveToThread(&thread);
thread.start();
return a.exec();
}
#include "main.moc"

QThread Memory Leak

main.cpp:
#include <QCoreApplication>
#include <QtCore>
#include "myobject.h"
QThread* cThread;
MyObject* cObject;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cThread = new QThread();
cObject = new MyObject();
cObject->moveToThread(cThread);
QObject::connect(cThread, SIGNAL(started()),
cObject, SLOT(doWork()));
QObject::connect(cThread, SIGNAL(finished()),
cThread, SLOT(deleteLater()));
QObject::connect(cThread, SIGNAL(finished()),
cObject, SLOT(deleteLater()));
cThread->start();
return a.exec();
}
myobject.cpp:
#include "myobject.h"
MyObject::MyObject(QObject *parent) :
QObject(parent)
{
}
void MyObject::doWork()
{
qDebug() << "Hi";
QThread::currentThread()->quit();
return;
}
myobject.h:
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QtCore>
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0);
signals:
public slots:
void doWork();
};
#endif // MYOBJECT_H
Apparently, according to: https://stackoverflow.com/a/16062717, there is a memory leak, but how do I fix it? I guess I would have to return to the event loop and then call quit? But the issue is that I don't have access to the event loop.
There isn't a memory leak. Qt does clean up properly if you stick to its object model, and object trees and ownership. I also like following the documented examples.
Here is the example you referenced, with observation added on deleteLater().
main.cpp
#include <QCoreApplication>
#include <QtCore>
#include <QThread>
class MyThread : public QThread
{
Q_OBJECT
public slots:
void deleteLater()
{
qDebug() << Q_FUNC_INFO;
QThread::deleteLater();
}
};
class MyObject : public QObject
{
Q_OBJECT
public:
explicit MyObject(QObject *parent = 0){}
signals:
public slots:
void deleteLater()
{
qDebug() << Q_FUNC_INFO;
QObject::deleteLater();
}
void doWork()
{
qDebug() << "Hi";
QThread::currentThread()->quit(); // It is supposed to stop here, but it doesn't.
return;
for (int i = 0; i < 1000000; i++) {
qDebug() << i;
}
}
};
QThread* cThread;
MyObject* cObject;
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
cThread = new MyThread();
cObject = new MyObject();
cObject->moveToThread(cThread);
QObject::connect(cThread, SIGNAL(started()),
cObject, SLOT(doWork()));
QObject::connect(cThread, SIGNAL(finished()),
cThread, SLOT(deleteLater()));
QObject::connect(cThread, SIGNAL(finished()),
cObject, SLOT(deleteLater()));
cThread->start();
return a.exec();
}
output:
Hi
void __thiscall MyObject::deleteLater(void)
void __thiscall MyThread::deleteLater(void)
Hope that helps.
I am the poster on the link. There is in fact no memory leak with the default connection. By subclassing deleteLater and destructors like #phyatt did you obtain :
Hi
void MyObject::deleteLater()
virtual MyObject::~MyObject() Being deleted
void MyThread::deleteLater()
virtual MyThread::~MyThread() Being deleted
But If you use Qt::QueueConnection for instance in your connections you obtain:
Hi
void MyThread::deleteLater()
virtual MyThread::~MyThread() Being deleted
And the object cObject is leaked.
It is undocumented when the thread will effectively exit. So I cannot argue whether this behavior will always be the same. One possibility is to make the thread launcher responsible for doing the cleanup work. For instance:
void cleanup(){
cThread->exit();
cThread->wait();
delete cThread;
delete cObject;
}
To wrap things up, you don't have to fix anything with this code.