Problem With Qthread signal and slot
-
Hi lalyperu,
Please read through the "QThread documentation ":http://qt-project.org/doc/qt-5/QObject.html#thread-affinity carefully before trying to use QThreads.
Also, read "QObject | Thread Affinity":http://qt-project.org/doc/qt-5/QObject.html#thread-affinity to understand how signals and slots work between threads.
[quote]@class Sensor : public QThread@[/quote]A sensor is not a thread, and it doesn't manage a thread either. Therefore, a Sensor class should not inherit a QThread.
-
[quote author="seiko" date="1391636863"]
I typed a simple code for you to able understand what you gonna dothe follow is your Sensor class
[/quote]
No. Please don't follow this code.
It is wrong to move the object owning a thread to that same thread, just like you should not move QThread to itself. Don't pull those kinds of tricks.Keep in mind that QThread is a class that manages a thread. It represents some kind of handle to that thread, and provides a starting point for it's execution path in its run method. It is not a thread, it is a QObject that lives, just like any other QObject, in the thread it was created it or was moved to. A thread is not an object. It is a context of execution of your code.
-
well Andre I shocked from your comment ...
Who said "class Sensor" own SensorThread ..
And It isn't kind of tricks it looks like the same way to
Call "pthread_create" with a sync signals of event loop -
[quote author="seiko" date="1391677546"]well Andre I shocked from your comment ...
Who said "class Sensor" own SensorThread ..
And It isn't kind of tricks it looks like the same way to
Call "pthread_create" with a sync signals of event loop [/quote]You say that, in your code. Allow me to explain.
In your first code path, you declare a class Sensor. Inside, you create a QThread object, who's sole pointer you store inside your Sensor class. That's ownership, is it not? Then, in line 26 you move your Sensor class instance to this new thread. So, you have moved the object that owns the QThread to the tread that manages that same QThread. -
Well Andre I only stored pointer to be able to call deleteLater() at the end
And that's not mean object ownership , that isn't "setParent"
moveToThread gonna create a new "QThreadData" for sensor class
without saving the pointer
then its gonna send ThreadChange Event to prepare move
then setThreadData_helper gonna call under mutex lock
so no problem gonna happenedAt the end Andre maybe you are right , and you see something I don't understand yet on qt , I'm still new with qt and also using qt only on GUI painting instead of GTK
Thank you again Andre for giving your time to help folks
-
I want to thank you for your collaboration.It's very helpful for me
-
I'm with Andre here.
First off, if you read the "Notes" section of the "QThread":http://qt-project.org/doc/qt-4.8/qthread.html docs you will find two excellent examples of how threading should be done with Qt (written, in fact, by Andre ;o).
Second, I've found that creating a class which manages both the thread and the worker as well as providing an interface to the rest of the application makes this far easier to understand and maintain. See the following very basic example:
sensor.h
@
#ifndef SENSOR_H
#define SENSOR_H#include <QObject>
#include <QThread>
#include <QDebug>class SensorWorker : public QObject{
Q_OBJECT
public:
explicit SensorWorker(){}
public slots:
void run(){
qDebug() << "Sensor Thread:" << QThread::currentThreadId();
}
};class Sensor : public QObject
{
Q_OBJECT
public:
explicit Sensor(QObject *parent = 0);
~Sensor();public slots:
void start();
void stop();private:
QThread *thread;
SensorWorker *worker;
};#endif // SENSOR_H
@sensor.cpp
@
#include "sensor.h"Sensor::Sensor(QObject *parent) :
QObject(parent)
{
thread=new QThread(this);worker=new SensorWorker(); connect(thread, SIGNAL(started()), worker, SLOT(run())); worker->moveToThread(thread);
}
Sensor::~Sensor(){
stop();
}void Sensor::start(){
thread->start();
}void Sensor::stop(){
if(!thread->isRunning()) return;
thread->quit();
thread->wait();
}
@widget.h
@
#ifndef WIDGET_H
#define WIDGET_H#include <QtGui/QWidget>
#include "sensor.h"class Widget : public QWidget
{
Q_OBJECTpublic:
Widget(QWidget *parent = 0);
~Widget();private:
Sensor *sensor;
};#endif // WIDGET_H
@widget.cpp
@
#include <QVBoxLayout>
#include <QPushButton>#include "widget.h"
Widget::Widget(QWidget *parent)
: QWidget(parent)
{
sensor=new Sensor(this);QVBoxLayout *l=new QVBoxLayout(this); QPushButton *start=new QPushButton("Start", this); connect(start, SIGNAL(clicked()), sensor, SLOT(start())); l->addWidget(start); QPushButton *stop=new QPushButton("Stop", this); connect(stop, SIGNAL(clicked()), sensor, SLOT(stop())); l->addWidget(stop);
}
Widget::~Widget(){}
@main.cpp
@
#include <QtGui/QApplication>
#include "widget.h"int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();qDebug() << "Main Thread:" << QThread::currentThreadId(); return a.exec();
}
@Hope this helps ;o)
-
You example was very clear and helpful for me.... But now I want to post another question...Only for test I implemented this code...
testwork.h
@
#include <QtCore/qobject.h>
#include <QtCore/qdebug.h>
#include <QtCore/qthread.h>class testwork : public QObject
{Q_OBJECT
public:
testwork();
~testwork();signals:
void finished();
public slots:
void setVariable();
void process();private:
int buttonvar;};@
testwork.cpp
@
#include "testwork.h"testwork::testwork()
{
buttonvar=0;
}testwork::~testwork()
{}
void testwork::process()
{
qDebug() <<"Function Process "<<"Thread ID: "<< QThread::currentThreadId()<< endl;switch (buttonvar)
{
case 1:
emit finished();
};
}void testwork::setVariable()
{
buttonvar =1;
}@main.cpp
@
#include "testwork.h"int main(int argc, char *argv[]) {
QApplication a(argc, argv);
qDebug() << "Main Page init "<<"Thread Id:" << QThread::currentThreadId()<< endl;QWidget *window = new QWidget;
QPushButton *setbutton = new QPushButton("set var ");
QHBoxLayout *layout = new QHBoxLayout;layout->addWidget(setbutton);
window->setLayout(layout);
QThread* thread = new QThread; testwork* worker = new testwork(); worker->moveToThread(thread);
QObject::connect(thread, SIGNAL(started()), worker, SLOT(process()));
QObject::connect(setbutton, SIGNAL(clicked()), worker, SLOT(setVariable()));
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();
window->show();return a.exec();
}@
The QObject connections between the button setbutton and the slot setVariable doesn't work.. so if a clicked the button nothing happens.Is There something wrong?
Thank you :)
-
Hi,
How can you tell that testwork::setVariable() didn't work?
You only called testwork::process() once, when the thread starts. It will not run again by itself when you call testwork::setVariable().
-
Hi,
your question is right.. :) sorry there was my mistake in copy and paste the code.. I had inserted in setVariable slots a qDebug() <<"Set Variable called" only to see if the slot had been executed... but didn't happen...
So I had thought there was a problem in a code but it wasn't...I had to recompile the code, run and the code worked well... I didn't understand where was the problem..but now works...Thanks for your time