Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

QTimer destructors



  • Hi all, I sometimes receive this warning during termination of my application:

    QObject::killTimer: Timers cannot be stopped from another thread
    QObject::~QObject: Timers cannot be stopped from another thread
    

    I'm not explicitly calling the destructors in a different thread. Any guesses on how I'm accidentally causing this?



  • @John-Howe
    You may not be calling destructors explicitly, but do you parent the QTimers to (a QObject in) another thread?


  • Qt Champions 2017

    @John-Howe said in QTimer destructors:

    I'm not explicitly calling the destructors in a different thread. Any guesses on how I'm accidentally causing this?

    I'm going to respond to this the same way I had done in the past, here.

    Qt is going to free child QObjects when the parent is destroyed, so that's how you get to this. Why you get the warning exactly is anyone's guess without more information.



  • You simply need to defer starting the timer until after the thread is started because the thread has a different event loop and you want the timer running that event loop not the main thread's. Assume you have two objects, a QThread and a QObject-derived object you want to run in that thread, e.g. class MyWorker : public QObject. Create a slot MyWorker::OnThreadStarted and there is where you wire up the timeout and start the timer. The essential code to start the thread is below.

    // main thread application code
    MyWorker *worker_ = new MyWorker;  // do not parent the QObject
    QThread worker_thread_;
    
    worker_->moveToThread(&worker_thread_);
    connect(&worker_thread_, &QThread::started, worker_ , &MyWorker::OnThreadStarted);
    connect(&worker_thread_, &QThread::finished, worker_, &QObject::deleteLater);
    
    worker_thread_.start();
    

    N.B. The timer should be a member of MyWorker and parented to MyWorker. It's ok to create the timer in the main thread, e.g. in the constructor of MyWorker, but you must defer starting it until the thread is running. Somewhere else in your main application, perhaps a close event, you would typically stop and wait for (join) the worker thread:

    worker_thread_.stop();
    worker_thread_.quit()
    

Log in to reply