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 ¶meter) {
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?
Related
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.
I am writing a program that captures an Image from the Camera every REFRESH_RATE milliseconds to send it to some calculation algorithm. I decided to time the launch of this algorithm using a QThread, but the algorithm is running on the main thread, because I need objects created before in this one.
Anyway, this works well.
The trouble begins when I try to shut the second thread down... Here's the code.
Camera:
class Camera : public QMainWindow
{
Q_OBJECT
public:
Camera(QWidget *parent = 0){
AlgoQThread = new QThread;
myAlgoThreadWorker = new AlgoThreadWorker( (Camera *) this );
myAlgoThreadWorker->moveToThread(AlgoQThread);
//Launch The thread
connect(AlgoQThread, SIGNAL(started()), myAlgoThreadWorker, SLOT(process()));
connect(myAlgoThreadWorker, SIGNAL(finished()), AlgoQThread, SLOT(quit()));
// The line meant to stop the thread at next loop
connect(this, SIGNAL(stopAlgoThread()), myAlgoThreadWorker, SLOT(stopThread()));
connect(myAlgoThreadWorker, SIGNAL(finished()), myAlgoThreadWorker, SLOT(deleteLater()));
connect(AlgoQThread, SIGNAL(finished()), AlgoQThread, SLOT(deleteLater()));
AlgoQThread->start();
}
private slots:
void errorString(QString error);
//This function is triggered by a signal sent by the method called in AlgoThreadWoker::process()
void some_algorithm(){
...
emit stopAlgoThread();
}
signals:
void stopAlgoThread();
private:
QThread * AlgoQThread;
AlgoThreadWorker * myAlgoThreadWorker;
};
algoThreadWorker:
class AlgoThreadWorker : public QObject
{
Q_OBJECT
public:
AlgoThreadWorker(Camera * context){
parentCamera = context;
}
Camera* parentCamera;
public slots:
void process(){
while(1){
QMutexLocker locker(&m_mutex);
if (t_stop) break;
parentCamera->isCapturingImage = true;
//This triggers the some_algorithm() using a signal sent by imageCapture from main Thread
parentCamera->imageCapture->capture();
//Wait REFRESH_RATE millisecondes
Sleep(REFRESH_RATE);
}
//Ends the thread
emit finished();
}
private slots:
void stopThread(){
QMutexLocker locker(&m_mutex);
t_stop = true;
};
signals:
void finished();
void error(QString);
private:
bool t_stop;
QMutex m_mutex;
};
And well, as you may have foresee, it doesn't work. I can launch some_algorithm() with no problems but I can't end the thread. The stopThread() slot isn't even launched, I've tested that already.
Since you are busy waiting in your while loop, the event loop never gets a chance to process the received signals.
qApp->processEvents() gives the control to your event loop in order to process the awaiting jobs.
Note that generally you do not have to call it yourself, Qt does it for you. In your case, it is neccessary because you have an endless loop which prevents Qt from doing its job.
Solution :
void process(){
while(1){
qApp->processEvents();
^^^^^^^^^^^^^^^^^^^^^^
.....
}
//Ends the thread
emit finished();
}
stopThread() is private and thus only accessible from AlgoThreadWorker.
Qt's event loop already provides for safe cross-thread slot call and event delivery. Your mistakes are mostly to do with incorrectly reimplementing what Qt already provides:
Things are already thread-safe. Drop the mutex.
thread->quit() works and will exit from the event loop running in the given thread. In a QThread, the thread will then finish,.
Don't make your code non-portable for no reason (Sleep is Windows-specific). If you wish do things periodically, simply run a timer (QBasicTimer or QTimer).
This answer provides a complete example.
I'm currently trying to understand how signals and slots in Qt behave with threads.
I've tried to run a small test with the following code:
class Worker : public QObject{
Q_OBJECT
public:
Worker(int _value){value = _value;}
~Worker(){};
int value;
public slots:
void changeValue(int newValue){value = newValue;}
void doWork(){
while(1){
_sleep(500);
std::cout << "Value is " << value << std::endl;
if(value == 0)break;
}
emit finished();
}
signals:
void finished();
};
class Manager : public QObject{
Q_OBJECT
public:
Manager(){}
~Manager(){};
signals:
void modifiedValue(int value);
public:
void changeTheValue(int value){emit modifiedValue(value);}
};
Basically, the worker display its value member every once in a while, and has a slot with a function that modifies the value.
The manager has the only purpose of emitting a signal with a new value when changeTheValue is called, that maps to the slot in Worker that modifies the value member.
Then I make my Worker class work in a thread the following way :
QThread myThread;
Worker myWorker(10);
Manager manager;
myWorker.moveToThread(&myThread);
QObject::connect(&myThread, SIGNAL(started()), &myWorker,SLOT(doWork()));
QObject::connect(&myWorker, SIGNAL(finished()), &myThread, SLOT(quit()));
QObject::connect(&myWorker, SIGNAL(finished()), &myWorker, SLOT(deleteLater()));
QObject::connect(&myThread, SIGNAL(finished()), &myThread, SLOT(deleteLater()));
QObject::connect(&manager, SIGNAL(modifiedValue(int)),
&myWorker, SLOT(changeValue(int)));
myThread.start();
for(int i = 1; i < 10 ; i++){
_sleep(1000);
manager.changeTheValue(i);
}
manager.changeTheValue(0);
But nothing happens. The value doesn't seem to be changed: output show a dozen lines with Value is 10.
What I can't understand is, why does the signal/slot mapping with Manager::modifiedValue and Worker::changeValue does not seem to work ? Is it only because the thread is currently running the doWork()'s loop ? Where does the call to the slots ends up then (queued, discarded, other) ?
I couldn't find much more on how does the signals/slots mechanism work with threads (I only found this thread which explains in which thread's call stack does the call to the slot end up, but the link provided in the answer seems outdated and leads to Qt 5 home).
To sum up the questions:
Why does the call to the slot that modifies the value does nothing ?
Is it possible to make this work (adding thread-safety wherever necessary) and how ?
There are multiple modes of how signals and slots work with threads (you absolutely must use QThreads for these to work!). These are documented in the manual:
http://qt-project.org/doc/qt-4.8/threads-qobject.html#signals-and-slots-across-threads
The mistake in your code is that the Qt event loop is never called (as doWork never returns). For a repeating call you should be using a timer in that thread. Alternatively (NOT the recommended solution) you can call processEvents in your infinite loop.
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.
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.