Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Stop a QThread That Runs a Blocking Forever Loop?

Tags:

c++

linux

qt

I have some rough code that I've been experimenting with:

someserver.cpp (a GUI)

#include "server.h"
#include "ui_server.h"

Server::Server(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::Server)
{
    ui->setupUi(this);
}

Server::~Server()
{
    delete ui;
}

void Server::onBtnStartClicked()
{
    QThread worker; 
    worker.start(); // Start worker thread that goes into an infinite loop with a blocking call
}

void Server::onBtnExitClicked()
{
    // How do I cleanly stop worker from running?
    QApplication::quit();
}

worker.cpp

#include "worker.h"

Worker::Worker(QObject *parent) :
    QThread(parent)
{
}

void Worker::run()
{
    for (;;)
    {
        // a blocking IO call here like pipe, or msgrcv
        // process data received
    }
}

Since the worker thread runs in a forever loop with a blocking IO call, how will I be able to structure this so that when the Stop button is pressed in the GUI thread, the worker thread is stopped cleanly?

like image 458
Coding District Avatar asked Feb 11 '12 20:02

Coding District


People also ask

What is the use of quit in a qthread?

Quit is suited for a QThread starting it's event loop. The poll call will at a point in time return something, then the loop with run again, that's why the exit variable is used, once it's set to 0, next time poll returns, it will get out of the loop and end things gracefully. I dont inherit Qthread for my object.

What is a qthread in Qt?

A QThread object manages one thread of control within the program. QThreads begin executing in run (). By default, run () starts the event loop by calling exec () and runs a Qt event loop inside the thread. You can use worker objects by moving them to the thread using QObject::moveToThread ().

How to deal with a thread that is blocked indefinitely?

For example, a thread blocked indefinitely on an I/O operation may never return to check if it’s been killed. To correctly deal with this case, thread needs to be carefully programmed to utilize timeout loops as shown in the code given below. ...

Where does a qthread instance live in a thread?

It is important to remember that a QThread instance lives in the old thread that instantiated it, not in the new thread that calls run (). This means that all of QThread's queued slots and invoked methods will execute in the old thread.


2 Answers

You could of course put a boolean value within the for loop in Worker::run() checked every iteration, which breaks on ==true and is set by the gui Stop button. Of course, this won't quit the thread while execution is blocked.

Probably better is to get rid of the for loop and use Qt's signals and slots to setup a callback function, connected to a signal like QIODevice::readyRead(). These will be called only when there is information available in the socket/pipe whatever. Any other time you'll be able to quit the thread with QThread::exit(). You'll need to call QThread::exec() at some point as well to get the event loop going.

like image 72
Matt Phillips Avatar answered Oct 19 '22 16:10

Matt Phillips


in infinity loop paste this code and enjoy...

QTime dieTime = QTime::currentTime().addMSecs(1);
while( QTime::currentTime() < dieTime ) {
    QCoreApplication::processEvents( QEventLoop::AllEvents, 1);
}

don't forget

#include <QCoreApplication>

#include <QTime>

see you

like image 23
Stan Khalipa Avatar answered Oct 19 '22 16:10

Stan Khalipa