QThread deleteLater not called on application Quit

Threading in Qt is not very hard (so it seems).
But there's no definitive way to use use QThread. Look at the different articles and opinions.

My opinion is to be pragmatic and consider the context and situation of your problem, and just use what's best for it. :)

In this article I would like to describe a problem I had with threading. I've got a gui application that uses several threads. It's an application with multiple tabs, and every tab has got several (always running) threads. These threads are event-queue threads and are waiting on messages (jobs) they need to process.

My application uses memory-leak detection so when an object doesn't get deleted I get an horrible message at the end.

I've made the threads self-destroy when you call quit:

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

When you close the application directly via (Alt-F4 windows, or Cmd-Q on Mac) I destroy the different tabs an stop the threads.

I process this in the signal QApplication::aboutToQuit:

  thread->quit();
  thread->wait()

Calling quit ends the eventQueue of the thread and emits a finished() signal to the event queue..

But now there's a problem. I'm in the aboutToQuit signal. And it seems that the finished signal is placed on the event queue.

But the eventQueue isn't processed any more. The application exits the exec loop:

  qApp->exec();

When my application know exits I've got a problem the QThread is not deleted.

The finished() signal is placed on the qApp event queue, but isn't processed.

I've solved it by processing the eventQueue after my exec call.

int result =  qApp->exec();
int counter = 0;

while( qapp->eventDispatcher()->processEvents( QEventLoop::ExcludeUserInputEvents ) && counter < 25  ) 
{         
  ++counter;
}

I've created a loop to allow pending events to be processed. To be sure it will quit I've added a counter, but in my situation the loop is processed 2 times:

  • The first time: finished() is processed, and deleteLater() is posted to the eventQueue
  • The second time the deleteLater() is processed and the my QThread is deleted

Now I've finally got rid of that annoying memory leak message :)

** The non-deletion of QThread is not a real big issue, but the situation I describe here also applies to other slots I've connected to the finished() signal of the thread. These slot's aren't called without the method described above.