How to Stop a QThread That Runs a Blocking Forever Loop? - c++

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?

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.

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

To stop the worker thread it is necessary to add "stop requested" boolean flag, which should be tested at the beginning of each iteration. Also the synchronization is needed to read/write value of this boolean flag.
Here is the draft version:
class Worker : public QThread {
public:
Worker() : stopRequested(false) {}
void requestStop()
{
QMutexLocker locker(&mutex);
stopRequested = true;
}
void run()
{
forever
{
if (stopRequested())
break;
// a blocking IO call here like pipe, or msgrcv
// process data received
}
}
private:
bool stopRequested()
{
QMutexLocker locker(&mutex);
return stopRequested;
}
QMutex mutex;
bool stopRequested;
};

First of all, you should set the parent for Worker to make it a child of another QObject, to clean it right way when the app is done, and create it on heap. i.e. dynamic way .
Second, simplest way to do what you want is to define slot which will set boolean member of Worker object and check it in each cycle to break endless loop. Don't forget to connect this slot to a right signal.
so you can put in constructor of the Server along the lines
QThread * worker = new QThread (this);
connect (this, SIGNAL(terminator()), worker, SLOT(terminate()));
in Server class declaration:
signals:
terminator();
in class Worker :
private:
bool terminate_; // don't forget initialize it to false
public slots:
void terminate(){terminate_ = true;}
and in the cycle:
if (terminate_) {/* .. do exit things...*/; return;
after that emit signal terminator() from server whenever you need.
If you will need more complicated management then simple stop, you will probably need to protect your state variable with a mutex.

Here you have the explanation of you're problem, i think. When your application will end, you should do something like this :
MyClass::~MyClass()
{
m_thread->requestStop();
m_thread->wait(); // Force the thread trying to destroy
// an object of type MyClass, to wait
// the end of the execution of m_thread
delete m_thread;
}
wait() is the solution for your synchronisation problem. You could also change requestStop() to :
void requestStop()
{
mutex.lock();
stopRequested = true;
mutex.unlock();
wait();
}
Removing QMutexLocker is important to avoid a Deadlock situation.

Related

How to exit from QThread::wait()

I am using QThread for some huge task in background, here is sample
code i am using
class Worker : public QObject
{
Q_OBJECT
QThread workerThread;
public slots:
void doWork(const QString &parameter) {
while(1){
// some huge code here
......................
if(condition) break;
}
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, SIGNAL(finished()), worker, SLOT(deleteLater()));
connect(this, SIGNAL(operate(QString)), worker, SLOT(doWork(QString)));
connect(worker, SIGNAL(resultReady(QString)), this, SLOT(handleResults(QString)));
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
Is it recommended to use wait() after quit in above program?
My program sometimes stuck on QThread::wait(), it is downloading huge file from server and it take about 5-6 min to again check for while condition , I just want to exit from thread but main thread stuck at wait(), is there any way?? to exit or kill thread forcefully without crash or hang main application? I also tried QThread::terminated but it never works.
Any Help appreciated.
Thanks.
First of all it is not clear what you are doing at your thread from your above codes. Your first point of concentration is your method which is running inside your thread i.e. your thread object. First of all, why sometime your thread does not complete its task? and why it stuck? Here I can see a while loop with a condition always true. Probably you have some break statement inside the loop which sometimes never satisfy and because of that thread never complete as while loop is continuing. Just check closely what going wrong there. If while loop is creating the issue I can advice you with the following modification in your code. But you must be very careful because it should not exit before completing some very important task.
First modify your while loop like below:-
introduce one bool variable before the while loop
bool continued = true;
while(continued)
{
//your codes
}
Now add one method in your thread object Worker
void stopWorker()
{
continued = false;
}
Now just call this method when you want your thread to exit by force
worker->stopWorker();
Since Qt 5.2 there is a QThread::requestInterruption() this function alone that can e used to signal to your thread that it should stop working, however you MUST check in you long operation for QThread::isInterruptionRequested() and quit your loop or event loop:
http://doc.qt.io/qt-5/qthread.html#isInterruptionRequested
Official documentation for QThread class says:
bool QThread::wait(unsigned long time = ULONG_MAX)
Blocks the thread until either of these conditions is met:
The thread associated with this QThread object has finished execution (i.e. when it returns from run()). This function will return true if the thread has finished. It also returns true if the thread has not been started yet.
time milliseconds has elapsed. If time is ULONG_MAX (the default), then the wait will never timeout (the thread must return from run()). This function will return false if the wait timed out.
As you can see, ULONG_MAX is the default parameter for the method, and it forces the method to never timeout.
Is it a choice to add your own timeout in the method parameter?

Qt Thread with ping operation in Linux

I am trying to accomplish what looks like a very simple task... but it's being a nightmare instead.
I developed an app for a Linux Laptop. Inside the app, I would like to have an independent thread that continuously pings another PC (eg once every 5 seconds, forever... well, as long as the laptop is switched on).
Of course, when the PC that the app is pinging is not connected, the app has to work smoothly, without waiting for the ping operation to return... How can I achieve this?
At first I used a QTimer with QProcess:execute("ping"...), which works fine. The problem is that if the other PC doesn't reply, my whole app and its GUI freeze for about one second at each ping operation. Changing the "ping" options (setting "-i0.2", for example), in order to reduce waiting time for the ping operation, didn't help: when the other PC is not connected my app becomes very slow. If I remove the ping, of course everything works smoothly.
So, I decided to insert the "ping" operation in a QThread, but when I try to follow the second example in http://doc.qt.io/qt-4.8/qthread.html, nothing seems to work: the app doesn't even start.
Here's the code:
//Pinger.h
class Pinger : public QThread
{
Q_OBJECT
void run();
public:
void setParam(const QString &urlToPing); // it sets the url to ping
signals:
/// \brief Signal emitted when pinging of specified url fails
void pingFailed(int ok);
private:
QString pingurl;
};
//Pinger.cpp
void Pinger::run()
{
int exitCode;
QProcess pingProc;
while(true)
{
exitCode=pingProc.execute("ping",QStringList() << "-c 1" << "-i0.2" << pingurl);
emit pingFailed(exitCode);
sleep(5);
}
}
// MainWindow::MainWindow
pinga= new Pinger(); // defined in mainwindow.h as Pinger* Pinga
pinga->setParam(ip_address);
connect(pinga,SIGNAL(pingFailed(int)),this,SLOT(connectionLost(int)));
connect(pinga,SIGNAL(finished()),pinga,SLOT(deleteLater()));
pinga->start();
Has anyone tried anything similar? I am quite new to Qt, but this operation seems so trivial that I find it incredible that there's no clear way to implement it. so I hope I am just missing something obvious.
If QThread is used it is better to avoid sleep(5); and the loop while(true), since the thread cannot be closed gracefully without killing it. Instead of the loop and blocking sleep it is better to call that periodic task again by single shot timer initiated when the previous task (process execution) is finished. However, in that case that logic should be implemented in some other member slot (Pinger::doWork()). The slot run() should be kept with its default implementation that executes the tread event loop. The work can be started by connecting the QThread::started() signal with Pinger::doWork():
connect(pinga, SIGNAL(started()), pinga, SLOT(doWork()));
It is needed to be careful with QThread deletion. In general it is not good to delete QThread object by itself (calling deleteLater() from its finished() signal). It is better to stop the thread and to delete it in MainWindow destructor:
MainWindow::~MainWindow
{
// stop the even loop
pinga->quit();
// wait for finishing current thread task; it can work only
// if the thread is not blocked by while(true) with sleep
pinga->wait();
// delete if it is not a smart pointer
delete pinga;
}
It is also possible to use QProcess with its non-blocking API in the main GUI thread without QThread. In that case it should be started by QProcess::start() and the slots connected to the signals QProcess::error() and QProcess::finished() should be used to start the next iteration. Those slots also should not block the main thread, so the next ping should be started using QTimer once previous ping is finished.
Here is an example of the "Qt Way" to write your Pinger class. Note that no threads are needed. QProcess is used asynchronously, and reports its status through a Qt signal. Once you really grok Qt, you'll realize that using threads is very rarely the right or most natural solution to these types of problems.
Note that I'm using Qt 5 with C++11 support enabled to connect Qt signals to C++11 lambdas... you could just as easily write it in Qt4 style but it wouldn't be as compact and readable.
class Pinger : public QObject
{
Q_OBJECT
public:
Pinger(QObject *parent = 0) : QObject(parent)
{
//Have to do this ugliness because QProcess::finished is overloaded
auto finishedFunc = static_cast<void(QProcess::*)(int)>(&QProcess::finished);
connect(&m_process, finishedFunc, [this](int exitCode)
{
if( exitCode == 0 )
{
emit pingSuccess();
}
else
{
emit pingFailed(exitCode);
}
});
}
void run(const QString& hostToPing, int intervalInSeconds)
{
m_host = hostToPing;
QTimer* timer = new QTimer(this);
timer->start(intervalInSeconds * 1000);
QObject::connect(timer, &QTimer::timeout, [this]()
{
if ( m_process.state() == QProcess::NotRunning )
{
m_process.start(QString("ping -c 1 -W 1 %1").arg(m_host));
}
else
{
qDebug() << "Cannot ping, previous ping operation still in progress!";
}
});
}
signals:
void pingSuccess();
void pingFailed(int exitCode);
private:
QProcess m_process;
QString m_host;
};
Using it is as simple as:
Pinger pinger;
QObject::connect(&pinger, &Pinger::pingSuccess, []()
{
qDebug() << "Host is up!";
});
QObject::connect(&pinger, &Pinger::pingFailed, [](int exitCode)
{
qDebug() << "Host is unreachable! Ping exit code = " << exitCode;
});
pinger.run("google.com", 3);
I had the same problem and fixed it by running the ping command in an own thread. By using a signal, I'm interacting with the non-blocking GUI.
1) I've declared a Ping class, which run the Ping command:
class Ping {
public:
static bool start(QString host) {
QStringList parameters;
#if defined(WIN32)
parameters << "-n" << "1";
#else
parameters << "-c 1";
#endif
parameters << host;
int exitCode = QProcess::execute("ping", parameters);
if (exitCode==0) {
return true;
} else {
return false;
}
}
};
2.) Additionally I've a NetworkReceiver class, which creates the Network Thread via a Slot (startConnectionCheck) and interacts with the GUI via a Signal (newConnectionStatus):
class NetworkReceiver : public QObject
{
Q_OBJECT
public:
explicit NetworkReceiver(QObject * parent = nullptr);
~NetworkReceiver();
void start() {
while(true) {
emit newConnectionStatus(Ping::start("google.at"));
QThread::sleep(5);
}
}
signals:
void newConnectionStatus(bool connected);
public slots:
void startConnectionCheck() {
QFuture<void> test = QtConcurrent::run(this, &NetworkReceiver::start);
}
};

How to process signals & events properly from long running task in a QThread

I'm trying to create a thread that runs a server in QT. The server runs in a polling loop until its told to stop. I'd like to be able to add slots to my class so I can do stuff such as stop the server from a signal.
QT seems to have a pretty convoluted history with QThread so I've been reading up on blogs about doing threads right and this is what I've come up with.
MyServer is a class derived from QObject:
class MyServer : public QObject {
Q_OBJECT
public slots:
void run();
void stop();
signals:
void finished();
private:
void init();
void pollForConnections(int ms);
void cleanup();
};
I can run the server from a thread by creating my object, creating a QThread, moving the server to the thread's ownership, connecting up some signals and invoking start():
MyServer *server = new MyServer();
QThread *serverThread = new QThread();
server.moveToThread(serverThread);
// Cause thread to delete itself when server finishes
QObject::connect(serverThread, SIGNAL(started()), server, SLOT(run()));
QObject::connect(server, SIGNAL(finished()), serverThread, SLOT(deleteLater()));
serverThread->start();
So when the QThread starts it emits a started() signal and my run() slot is invoked by the started() signal. The run() method is a loop which spins around until it is told to stop:
void MyServer::run() {
init();
while (true) {
{
QMutexLocker lock(&mutex_);
if (stop_) {
break;
}
}
pollForConnections(100); // 100ms is timeout
}
cleanup();
emit finished();
}
void MyServer::stop() {
QMutexLocker lock(&mutex_);
stop_ = true;
}
The issue here of course is that started() will not return to the QThread because it's in my loop. And since my loop has no processing for signals, I couldn't connect stop() to another signal. So presently I just invoke stop() from any thread and use a mutex to protect the flag while I do.
QT has a QEventLoop which I could modify the loop:
QEventLoop eventLoop;
while (true) {
if (stop_) {
break;
}
pollForConnections(100); // 100ms is timeout
eventLoop.processEvents();
}
So potentially I could hook stop() to a signal of some kind and I don't need a mutex to protect stop_ because it will be run on my own thread. I could also process events as I spin around.
This appears to function but I wonder if this is good practice - don't forget that I'm still hanging off that started() signal so are there reentrancy problems here? Also, once I drop out of my loop, is the QThread going to drop into it's default exec() and then run forever? Is it sufficient that by emitting finished() and invoking deleteLater() that the thread will sort itself out properly?
You'd have a better design if you just used QThread's default run() method, and signals-and-slots as your mechanism for everything.
In particular, instead of having a mutex and a polled boolean, you can connect a signal to the thread's quit() method, and when you want the thread to go away, just emit that signal.
Also, there's almost certainly a better way to check for connections than polling for them. The problem with polling (in this case anyway) is that it blocks execution of the thread's other duties for up to 100mS, which will make the thread perform slowly. It also means the thread is using up some CPU cycles every 100mS, even when 99% of the time no connections are actually incoming. Assuming these are TCP connections, check out the QSocketNotifier and/or QTCPServer classes, either of which can handle incoming TCP connections without polling.
Also, once I drop out of my loop, is the QThread going to drop into
it's default exec() and then run forever?
Only if you explicitly call up to QThread::run().
Is it sufficient that by emitting finished() and invoking deleteLater() that the thread will sort itself out properly
It might work, but I think calling QThread::quit() or QThread::exit() (and using the default event loop) would be a better practice.
MyServer.h
class MyServer : public QObject {
Q_OBJECT
public:
bool isRuning() const;
public slots:
void run();
void stop();
signals:
void finished();
private:
void init();
//don't need in this method
//void pollForConnections(int ms);
void cleanup();
mutable QMutex m_mutex;
};
MyServer.cpp
void MyServer::run() {
init();
while (isRuning()) {
//some code here with signals
}
cleanup();
emit finished();
}
void MyServer::stop() {
QMutexLocker locker(&m_mutex);
stop_ = true;
}
bool isRuning() const {
QMutexLocker locker(&m_mutex);
return stop_;
}
You don't need in QEventLoop. All signals from your infinite loop in while queued to the main thread events queue, if exist connection with object from main thread.
run method calling not from main thread, his call also queued to separate event queue.
After finished signal, serverTread object is queued for deleting via deleteLater method.

How to stop looping thread

I want to stop a looping thread when a signal was emitted so here is my code
void MyThread::stopWatchingThread()
{
qDebug()<<"MyThread::stopWatchingThread()";
Keep_running=false;
qDebug()<<"MyThread::stopWatchingThread Keep_running"<<Keep_running;
...
}
void MyThread::run()
{
qDebug()<<"MyThread::run()";
qDebug()<<"MyThread::run Keep_running"<<Keep_running;
while(Keep_running)
{
...
}
qDebug()<<"MyThread::run Keep_running"<<Keep_running;
Keep_running=false;
qDebug()<<"MyThread::run Keep_running"<<Keep_running;
}
void Watcher::Init()
{
WatchingThread=new MyThread(this->L_RootToWatch);
connect(this,SIGNAL(stopmonotiring()),WatchingThread, SLOT(stopWatchingThread()));
...
}
void Watcher::StartWatching()
{
WatchingThread->start();
}
void Watcher::StopWatching()
{
emit stopmonotiring();
}
So every thing goes all right but my problem is that Keep_running never get false value in MyThread::run() after emitting stopWatchingThread and so while loop for ever.
What did I miss ?
any help will be appreciated.
Don't create threaded classes explicitly in Qt. Instead, create a worker object, move that object to a QThread, then call start() on the QThread. Here's a quick example:
class Worker : public QObject
{
Q_OBJECT
public:
Worker( QObject * parent = 0 )
: QObject( parent )
{}
public slots:
void doWork( ... )
{
// do work here
}
void stopMonitoring()
{
emit finished();
}
signals:
void finished();
};
int main()
{
Worker * w = new Worker();
QThread * thread = new QThread();
QObject::connect( w, SIGNAL(finished()), thread, SLOT(quit())
QObject::connect( w, SIGNAL(finished()), w, SLOT(deleteLater())
QObject::connect( thread, SIGNAL(finished()), thread, SLOT(deleteLater())
w->moveToThread( thread );
thread->start();
// some other object emits a signal connected to the 'doWork()' slot.
}
I omitted some of the standard QApplication boiler-plate, but you have that already if you're using Qt. This should get you started.
As your run() method is blocking and the event loop never entered, the slot stopWatchingThread will never be called. You must call exec() and not block the event loop by a spinning loop in run(). Either that, or have the watcher thread call stopWatchingThread directly instead of using a signal/slot connection. I'd go for the latter. keepRunning will be accessed from multiple threads then, so you have to protect it using a QMutex, QReadWriteLock or QAtomic. (Start with QMutex, it's easiest).
If you use an event loop in your thread just post the quit() signal to the thread object.
Maybe your C++ compiler optimizes away the read operation on Keep_running. Try declaring it as volatile, which tells the compiler that this variable might change "unexpectedly", e.g. from other threads or hardware interrupts.

Is it possible to implement polling with QThread without subclassing it?

I have a class, which is an abstraction of some device.
class Device
{
public:
...
void Start();
void Stop();
void MsgLoop();
signals:
void sMsgArrived();
}
Start() and Stop() are called from GUI thread. Start() begins new thread, which runs MsgLoop(). It looks like this:
void MsgLoop()
{
forever {
if(SUCCESS == ReadMsg()) //synchronous, non-blocking
{
ProcessMsg(); //quite fast
emit sMsgArrived(); //this signal is connected with a slot in GUI thread
}
}
}
When Stop() is called, program should return from MsgLoop() and stop the thread. How can I implement this with QThread without subclassing it?
Generally you have to decide who will be responsible for managing the thread. Is it the Device or the main window? Or possibly some device manager. In your case the Device should probably manage its own thread, so if you don't want to subclass it, use composition:
class Device : QObject
{
Q_OBJECT
public:
Device(QObject * parent = NULL);
void Start();
void Stop();
private slots:
void MsgLoop();
signals:
void sMsgArrived();
private:
QThread thread;
bool stopThread;
};
Device::Device(QObject * parent) : QObject(parent)
{
moveToThread(&thread);
connect(&thread, SIGNAL(started()), this, SLOT(MsgLoop()));
}
void Device::Start()
{
stopThread = false;
thread.start();
}
void Device::Stop()
{
stopThread = true;
thread.wait(); // if you want synchronous stop
}
void Device::MsgLoop()
{
// your loop
while(!stopThread)
if(SUCCESS == ReadMsg())
{
ProcessMsg();
emit sMsgArrived();
}
QThread::currentThread->quit();
}
NOTE: the thread stopping will only work if ReadMsg really is non-blocking. If you later decide to switch to blocking read (and that would probably be appropriate for most cases), you will have to figure out another way how to stop your thread.
If you look at this link you can see that it is possible to run a method in a separate thread without subclassing a QThread.
However what you are asking is running a message loop forever.
If you follow the given example you can run your loop without subclassing but the QThread object will never enter into its own message loop cause it will never return from your slot. So here is an example but I think it would be a bad design
class Device : public QObject
{
Q_OBJECT
public:
Device(QObject* parent = 0);
~Device();
public Q_SLOTS:
void MsgLoop();
};
QThread* thread = new QThread;
Device* device = new Device;
void Widget::onBtnStartClicked()
{
device->moveToThread(thread);
//This will call start method of Device
connect(thread, SIGNAL(started()), device, SLOT(MsgLoop()));
//This will start the event loop of thread
thread->start();
}
void Widget::onBtnStopClicked()
{
//Tells the thread to exit
thread->exit(0);
}
I am afraid you have to subclass a QThread if you want to run a forever loop.
IMHO you shouldn't. Polling requires being in a forever loop. You must do this in QThread's run function so there is no way to re-implement a function without sub-classing first. Even if you were to try and workaround it with a single shot timer I don't recommend it. You are better off(this is how i like to do it) sub-classing QThread, calling moveToThread(), not call exec() and put a forever loop in run. For an example of this look at the Fortune Blocking Client example from qt. If you don't call moveToThread() on QThread then the QThread object still resides in the GUI main thread and they both share the same event loop (which is bad when using polling functions). Calling moveToThread(QThread) without calling exec() means the QThread will not have an event loop(which is good in your case). Calling exec() would start it's own event loop but is not used for polling schemes and you would leave the run function.