I have a class like this:
class myClass:public QThread
then in its constructor I did:
myClass::myClass(){
moveToThread(this);
...
}
It seems that all the member slots are actually working on the worker thread.
But how could I stop the thread during the deconstruction in this case?
Simply don't do threading like that.
The proper way to use moveToThread() is described in Qt docs:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
/* ... here is the expensive or blocking operation ... */
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, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
or by inheriting QThread, like:
class WorkerThread : public QThread
{
Q_OBJECT
void run() Q_DECL_OVERRIDE {
QString result;
/* ... here is the expensive or blocking operation ... */
emit resultReady(result);
}
signals:
void resultReady(const QString &s);
};
void MyObject::startWorkInAThread()
{
WorkerThread *workerThread = new WorkerThread(this);
connect(workerThread, &WorkerThread::resultReady, this, &MyObject::handleResults);
connect(workerThread, &WorkerThread::finished, workerThread, &QObject::deleteLater);
workerThread->start();
}
but not both of them at the same time.
More on that topic here
Related
It was my first attempt to create a thread in qt but unfortunately it isn't stopping. This is how my code look like.
// Worker class
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
forever{
if(QThread::currentThread()->isInterruptionRequested()){
printf("true");
return;
}else{
if(!QThread::currentThread()->isInterruptionRequested()){
cout<<parameter.toStdString();
}
}
}
emit resultReady(result);
}
signals:
void resultReady(const QString &result);
};
// Controller class
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller(QObject *parent = nullptr):QObject(parent) {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void stop(){
workerThread.requestInterruption();
}
signals:
void operate(const QString &);
};
The forever loop isn't stopping when stop function is called.Have I done anything wrong?
http://doc.qt.io/qt-5/qthread.html
class Controller : public QObject
{
Q_OBJECT
QThread workerThread;
public:
Controller() {
Worker *worker = new Worker;
worker->moveToThread(&workerThread);
connect(&workerThread, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
My way:
class Controller: public QObject
{
Q_OBJECT
public:
Worker objWorker;
QThread objQThread;
Controller();
~Controller();
public slots:
void receiveImage();
};
and
Controller::Controller()
{
objWorker.moveToThread( &objQThread );
connect( &objWorker, &Worker::imageReady, this, &Controller::receiveImage );
objQThread.start();
}
Is their method better than mine in some way? Which should be preferred in which case?
From: http://doc.qt.io/qt-5/qthread.html
From Qt 4.8 onwards, it is possible to deallocate objects that live in
a thread that has just ended, by connecting the finished() signal to
QObject::deleteLater().
This can be achieved only by making a pointer object of the Worker class and allocating memory to it.
I am trying to update gui from another thread by using this: https://stackoverflow.com/a/14546167/2236297
This is my workerthread:
class WorkerThread : public QThread {
void run() {
while(1) {
//QTcpSocket messenger;
//messenger.connectToHost("192.168.1.20", 61000);
//if(!messenger.waitForConnected(3000))
//{
emit progressChanged("111");
//}
}
}
// Define signal:
signals:
void progressChanged(QString q)
{
}
};
Only difference is I declared this class as a inner class and defined progressChanged. In his example signal was just declared, not defined.
My onProgressChanged:
void ApplicationController::onProgressChanged(QString info)
{
// Processing code
ui.label_2->setText("Latest info: " + info);
}
This is how I start thread in my constructor:
ApplicationController::ApplicationController(QWidget *parent, Qt::WFlags flags)
: QMainWindow(parent, flags)
{
ui.setupUi(this);
WorkerThread *workerThread = new WorkerThread;
// Connect our signal and slot
connect(workerThread, SIGNAL(progressChanged(QString)),
SLOT(onProgressChanged(QString)));
// Setup callback for cleanup when it finishes
connect(workerThread, SIGNAL(finished()),
workerThread, SLOT(deleteLater()));
// Run, Forest, run!
workerThread->start(); // This invokes WorkerThread::run in a new thread
}
Question is: why my slot isn't called. What should I change?
EDIT
Changed workerthread.
.h file
class WorkerThread : public QThread
{
Q_OBJECT
public:
WorkerThread();
~WorkerThread();
void run();
private:
signals:
void progressChanged(QString info);
};
.cpp file
WorkerThread::WorkerThread() { }
WorkerThread::~WorkerThread() { }
void WorkerThread::run()
{
while(1) {
QTcpSocket messenger;
messenger.connectToHost("192.168.1.20", 61000);
if(!messenger.waitForConnected(3000))
{
emit progressChanged((QString("%1").arg(messenger.error())));
}
}
}
In debug, emit works. But slot is not called in main function.
SOLVED
There are multiple errors:
First of all workerThread should be defined as seperate class not an inner class.
Slot should be declared under slots:
public slots:
void onProgressChanged(QString info);
I have a problem with signal/slots in a QThread class. My design looks like this:
class Manager : public QObject {
Q_OBJECT
public:
Manager(QObject* parent) : QObject(parent) {
Thread thread* = new Thread(this);
connect(this, SIGNAL(testsignal()), thread, SLOT(test()));
thread->start();
...
emit testsignal();
}
signals:
void testsignal();
};
class Thread : public QThread {
Q_OBJECT
public slots:
void test() {
qDebug() << "TEST";
}
private:
void run() {}
};
The signal never reaches my test() method. Can someone help? Thanks.
The problem is that sending signals across threads results in queuing the signal into the target thread's event queue (a queued connection). If that thread never processes events, it'll never get the signal.
Also, according to the QThread::run documentation:
Returning from this method will end the execution of the thread.
In other words, having an empty run method results in instant termination of the thread, so you're sending a signal to a dead thread.
Signals sent to a QThread object will go to the thread of the parent object. In this case to the same thread that created it.
To have a object live on another thread you should move it to that thread:
class Manager : public QObject {
Q_OBJECT
public:
Manager(QObject* parent) : QObject(parent) {
Thread thread* = new QThread(this);
Receiver* rec = new Receiver(); //no parent
connect(this, SIGNAL(testsignal()), rec, SLOT(test()));
connect(thread, SIGNAL(finished()), rec, SLOT(deleteLater()));
rec->moveToThread(thread);
thread->start();
...
emit testsignal();
}
signals:
void testsignal();
};
class Receiver: public QObject {
Q_OBJECT
public slots:
void test() {
qDebug() << "TEST";
}
};
I have a C++ class. It inherits a parent class which inherits QQuickItem. Therefore now I can't inherit from QThread since the QQuickItem is already there.
(Error if tried: Object is an ambiguous base of 'xClass')
My class has been registered by qmlRegisterType and I can access its methods through QML.
There is a piece of code which runs when a button is pressed from QML. This piece of code takes a lot of time to execute and it steals the focus from QML window totally.
How to write a piece of code in my C++ class which when I run doesn't steal all the focus to itself?
One way to move a blocking process to a new thread is to create a worker object by subclassing QObject. Then use signals and slots to signal when the thread should process some data and to return the data.
Here is an example from Qt docs:
class Worker : public QObject
{
Q_OBJECT
public slots:
void doWork(const QString ¶meter) {
QString result;
/* ... here is the expensive or blocking operation ... */
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, &QThread::finished, worker, &QObject::deleteLater);
connect(this, &Controller::operate, worker, &Worker::doWork);
connect(worker, &Worker::resultReady, this, &Controller::handleResults);
workerThread.start();
}
~Controller() {
workerThread.quit();
workerThread.wait();
}
public slots:
void handleResults(const QString &);
signals:
void operate(const QString &);
};
You can find more threading technologies here. Check them all out and decide which one suits your needs the best.