[Solved] Stopping a QThread



  • Hi, I'm following the example from the wiki: http://qt-project.org/wiki/QThreads_general_usage

    If I have a long running function in the worker object and I want to stop the thread early, what is the correct way to do that ? Calling QThread::quit() wouldn't do anything because the example doesn't use an event loop.

    I'm thinking that with this example, it's not possible, you would have to subclass the QThread object and then have the worker calculate the function in chunks so that you could implement like this:

    @
    MyThread::run()
    {
    while(do_run)
    {
    worker->calculateChunkOfResult();
    }
    emit finished();
    }
    @

    As MyThread would live in the main thread I can just MyThreadObject->do_run = false when I want to stop.

    What I would prefer to do is connect a signal to the worker object to tell it to stop, but without an event loop in the worker object it's not going to process that signal until it finishes the long function.



  • yes i think the example is leaving something out. (they don't show the main() for example)

    i just ran the example as is provided and i get a
    QEventLoop: Cannot be used without QApplication

    when i add the QApplication you get the main event loop back, so ou can use the signals again.

    @int main(int argc, char *argv[])
    {
    QCoreApplication a(argc, argv);

    QThread* thread = new QThread;
    Worker* worker = new Worker();
    worker->moveToThread(thread);
    

    // QObject::connect(worker, SIGNAL(error(QString)), this, SLOT(errorString(QString)));
    QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
    QObject::connect(worker, SIGNAL(finished()), thread, SLOT(quit()));
    QObject::connect(worker, SIGNAL(finished()), worker, SLOT(deleteLater()));
    QObject::connect(thread, SIGNAL(finished()), thread, SLOT(deleteLater()));
    thread->start();

    return a.exec();
    

    }@

    in real life you'll have a QApplication though and subclassing QThread is what i normally do with a keepGoing variable to stop it, as you are already suggesting.
    plus you can implement a slot in your specialisation class to stop it (just set the internal keepGoing variable to false and let the loop run-out)

    is there a particular reason why you feel uncomfortable in overriding QThread ?



  • There were two threads asking the same question just last week.

    "link1":http://qt-project.org/forums/viewthread/34588/#150053

    "link2":http://qt-project.org/forums/viewthread/34537/#149815



  • clogwog

    I don't want to subclass QThread because I would like to keep the specifics of the function local to the worker class and not spread it into the thread class if possible. I also think it's a bit more elegant to keep a simple QThread class and all the complexity in the worker object.

    KA510

    Thanks for the links; I should have looked more closely at this forum - I read it so often I forgot to look when I came across this problem.

    I decided to adopt the solution of added a single shot timer to the worker object but I prefer to set a time of zero so there is just enough time for the event loop to process a halt message

    @
    QTimer::singleShot(0, this, SLOT(process()));
    @



  • bq. What I would prefer to do is connect a signal to the worker object to tell it to stop, but without an event loop in the worker object it’s not going to process that signal until it finishes the long function.

    QThread is the one having the local event loop, not the worker object ... not a problem to connect a signal from the app's main thread to a slot from other thread, but it will be queued by default and executed in the thread's event loop after the worker's long function ends up (because after moveToThread the worker will belong to the QThread object)... if you want to stop the long function earlier just do a direct connection with Qt::DirectConnection and the slot will be executed in the main thread


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.