[Qt-interest] Is it sensible to call "delete this; " at the end of a QThread's run method?

K. Frank kfrank29.c at gmail.com
Mon May 30 03:28:33 CEST 2011


Hi Chris!

Thank you for your reply and the deleteLater() suggestion.  I have a
few follow-up questions (see below).

On Sun, May 29, 2011 at 7:30 PM, Chris Vickery <chrisinajar at gmail.com> wrote:
> The thread affinity thing doesn't really make sense, if you remove that part
> then you can simply do this:

I don't know whether we have to resolve the thread-affinity issue to continue
this discussion.  If we don't need to, it might be simpler to just let it slide.

(For context, let me note that, among other places, the moveToThread issue
has been discussed in a thread I started:

   http://lists.qt.nokia.com/pipermail/qt-interest/2011-January/030205.html

Also, I am well aware of Brad Hughs's "You’re doing it wrong…" article:

   labs.qt.nokia.com/2010/06/17/youre-doing-it-wrong

My stance is the moveToThread is technically legal, does make sense, and
does work.  I acknowledge that there are many claims to the contrary, but I
don't know of any concrete explanations that back up those claims.)

Anyway, on to deleteLater()...

> connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));
>
> The signal name might be wrong, check the docs...

Thank you for this suggestion.  I have never used deleteLater(), and was
only vaguely aware of it.  Since it looks like the "Qt way" of doing things,
let me try to understand it.

I have some questions:

>From the description in the documentation (I am using Qt version 4.6.):

   void QObject::deleteLater ()   [slot]

   Schedules this object for deletion.

   The object will be deleted when control returns to the event loop. If the
   event loop is not running when this  function is called (e.g. deleteLater()
   is called on an object before QCoreApplication::exec()), the object will
   be deleted once the event loop is started.

   Note that entering and leaving a new event loop (e.g., by opening a modal
   dialog) will not perform the deferred deletion; for the object to be deleted,
   the control must return to the event loop from which deleteLater()
was called.

In general (not for my QThread case), because the QObject will be deleted
by the event loop from which deleteLater() was called, it sounds like the
nominal use case for deleteLater() would be for QObjects to schedule their
own deletion.  But, then, why not just have the QObject call "delete this"
after it's done with its event processing, just before returning control to the
(main) event loop?  Is there any practical difference here?

I'm having a hard time here imagining a canonical use case for deleteLater()
that can't be managed by "manually" calling delete at the "correct" time.  Is
deleteLater() primarily a convenience slot, or does it do something substantive
(and useful) that would be a nuisance to implement by hand?

> You're really better off using the thread object to fire off a worker class
> so that the thread affinity makes sense.

I do understand that with the thread affinity I happen to be using (i.e.,
"moveToThread (this)") using the connect call you suggest won't work:

   connect(this, SIGNAL(finished()), this, SLOT(deleteLater()));

The deleteLater() slot call will be directed to the QThread's event loop
(because of my QThread's thread affinity for itself), and that event loop
isn't running anymore (as the QThread's finished signal has been emitted).

But how about:

   connect(this, SIGNAL(finished()), mainGuiObject, SLOT(deleteWorkerThread()));

with

   void deleteWorkerThread() { delete workerThread_; }    // slot in
mainGuiObject

Is there any reason this won't work?  That is, I guess I'm asking if
it is guaranteed
safe to delete a QThread object ("delete pointerToThread;") if you do
so after its
finished signal has been emitted.

> You're going to get annoying thread object deleted while thread is still
> running errors, even if the event loop has exited. Basically it's impossible
> to properly clean up a QThread object that you've run moveToThread(this)
> on...

Do I understand you correctly that Qt will complain ("annoying ... errors") if
I call "delete this" in the QThread's run method?  I guess this is a legitimate
safety feature of Qt.  First, you don't want to accidentally delete a thread
while it's still "really" running.  Also, perhaps QThread calls some clean-up
or deregistration code after run exits, and this could get broken by calling
"delete this" within the run method.

I take it you're saying that "delete this" (within run()) is wrong and
potentially
dangerous, irrespective of the thread-affinity issue.  Is this right?

So then, let's say (for the sake of argument) that I keep on using
"moveToThread (this)".  Will the scheme of connecting the QThread's
finished() signal to a hand-coded slot in my main gui handler work,
a la my example above?

   void deleteWorkerThread() { delete workerThread_; }    // slot

>
> Chris

Thanks for your explanation and insights.


K. Frank


> ...
> On May 29, 2011 7:21 PM, "K. Frank" <kfrank29.c at gmail.com> wrote:
>> Hello List!
>>
>> I have a worker class derived from QThread, and now I want to be able
>> to clean up its instance programmatically while the application is
>> running, rather than just when the application terminates.
>>
>> I'm thinking of using QThread's quit slot to cause it to exit its event
>> loop, and then having the the run method execute delete(this).
>> ...



More information about the Qt-interest-old mailing list