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

How to restart a thread?



  • How to properly restart a QThread? I have been googling this four hours and can't find any concrete answer.

    What I have is the basic moveToThread implementation:

    VideoHandler::VideoHandler()
    {
        VideoBurner *videoBurner = new VideoBurner;
        videoBurner->moveToThread(&videoBurnerThread);
    
        connect(this, &VideoHandler::signalVideoData, videoBurner, &VideoBurner::setVideoData);
        connect(this, &VideoHandler::signalVideoBurn, videoBurner, &VideoBurner::initVideoBurn);
    
        // don't really want it since there is only 1 object
        //connect(&videoBurnerThread, &QThread::finished, videoBurner, &QObject::deleteLater);
    
        connect(videoBurner, &VideoBurner::burnProcess, this, [=](QString step, int percentage){
            emit burningProcess(step, percentage);
        });
    }
    

    This is the declaration of my Class:

    class VideoHandler : public QObject
    {
        Q_OBJECT
        QThread videoBurnerThread;
    ... 
    bunch of defintions
    ...
    }
    

    The VideoBurner class is also a subclass of QObject

    class VideoBurner : public QObject
    {
        Q_OBJECT
    ...
    bunch of definitions
    ...
    }
    

    For the first run this works perfect, signals and slots all work.
    The issue happens when I want to "cancel" the thread.
    For example it is working on some "heavy" calculation that I want to stop from the main thread so I call: videoBurnerThread.quit(); with a cancel function from VideoHandler.

    I don't wait() on it as it would block the main thread.

    quit() triggers &QThread::finished, but I commented out that connection as it destroys my only object instance.

    (also I can't find any example that creates an object and puts it on a thread outside a constructor, if that's even possible? when I tried the app would just close without errors)

    I found that the quit() only stops the event loop, not doing anything besides that, which leads to the issue of restarting the tread.

    After I want to do the "heavy" stuff again, and I call videoBurnerThread.start(); to start it again, I get results of last performed function from VideoBurner and some signals from it, before it actually starts doing what it should.

    Can I somehow stop whatever it was working on and just restart it? I tried sending an "abort" signal from VideoHandler so it doesn't emit signals, but that didn't work.

    Do I absolutely need the &QObject::deleteLater so it stops? If so, how to reinitialize VideoBurner correctly inside some function and reconnect it's signal/slot?

    Also there is no logic in VideoBurner destructor just a public: virtual ~VideoBurner(){};, could this be an issue?


  • Moderators

    @Wiru said in How to restart a thread?:

    For example it is working on some "heavy" calculation that I want to stop from the main thread so I call: videoBurnerThread.quit(); with a cancel function from VideoHandler.

    If your VideoBurner object is in the middle of a calculation and you quit the event loop, your VideoBurner will enter "suspended animation". It will remain stuck in its half-calculated state... and then it will continue the calculation when the event loop is restarted.

    To avoid that, you must get your VideoBurner object to discard its incomplete calculations when you want to quit.



  • @JKSH said in How to restart a thread?:

    If your VideoBurner object is in the middle of a calculation and you quit the event loop, your VideoBurner will enter "suspended animation". It will remain stuck in its half-calculated state... and then it will continue the calculation when the event loop is restarted.
    To avoid that, you must get your VideoBurner object to discard its incomplete calculations when you want to quit.

    Thank you for the info, I'll search for how to achieve this.


Log in to reply