After much testing and changes to my QT application, Visual Leak Detector identified the source of a pesky leak (8 bytes). VLD reported the QT application is clean except for a
A QThread
doesn't really know when its work is done. You can answer your own question by thinking of how you would implement this.
Its run()
method simply spins an event loop. Since all an event loop can know is if there are any events posted to it, the only condition you could reasonably implement is to quit the thread when there are no further events. This would make a thread quit immediately, so it's not helpful at all.
Perhaps you'd wish to terminate the thread when there are no more QObject
s that have the thread as their thread. This could certainly be implemented as an optional behavior in QThread
, but whether it's a change that would get accepted I don't know. It must not be a default behavior, since in many situations constant destruction and re-creation of threads is simply wasteful - one might want to retain a thread that has no objects on it.
Ultimately only you know when the thread's work is done. Your worker object can invoke thead()->quit()
or it can emit a signal when it's done - like you do already.
A QThread
cannot destroy itself when the work is done, since threads are restartable. You have full control over thread's lifetime, so you certainly can destroy it when its work is done, and you do already, only you do it wrong.
Your problem is really in the order that you wish for things to happen. The deleteLater
operation is performed by the event loop. If a thread's event loop isn't running, the deleteLater
is a NO-OP.
So, first of all, your connections should be done such that they form a cascade that can only execute in a well-defined order:
connect(thread, SIGNAL(started()), worker, SLOT(process()));
connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(worker, SIGNAL(destroyed()), thread, SLOT(quit()));
connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
Then, you must ensure that the thread where your processWorkQueue
method runs is not blocked and has a chance for its event loop to proceed. It's this event loop that will process thread's deletion.
As noted by AlexP, this doesn't work in Qt 4.7 or earlier, since all those versions had a bug in QThread's implementation. "QThread's behavior has changed" is an euphemism for "there was an ugly bug that finally fixed".
Your connect is overly verbose. You can drop spaces and reference/const-reference from the signature. The third argument is also optional if it's this
. It should look like:
connect(worker,
SIGNAL(updateMessageFromThread(QString,QString,QString,QString,
QString,QString,QString)),
SLOT(updateStatusBarFromThread(QString,QString,QString,QString,
QString,QString,QString)));
Answers:
QThread*
not destroying itself when the worker thread completed its work?Because there are different ways to use QThread
in which at least one must be able to query thread states or class members after worker has finished. Also the thread may be restarted.
QThread*
to delete the thread and worker object when work is complete?The finished
signal should be enough for you to call a slot deleting both.
QThread
be implemented differently?There are different implementations for different situations. http://qt-project.org/doc/qt-5.0/qtcore/thread-basics.html