简体   繁体   中英

creating new thread using Qthread-Qt5

I am trying to create a new thread gpsthread which should run in the back ground, and store the value.

class gpsthread: public QThread{
    Q_OBJECT
private:nrega_status_t status2;

public: 
explicit gpsthread(QObject *parent = 0):QThread(parent) {
    // QTimer *t = new QTimer(this);
    // connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
    // t->start(10000);
 }
 void run(){
    qDebug()<<"inside gps thread\n";
    QTimer *t = new QTimer(this);
     connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
     t->start(10000);
    }

public slots:void processgps(){
    int status2;
    status2=gps_management();
}
};

My main class is quickview.

int main(int argc, char *argv[])
{

QString file = "qml/main.qml";
QApplication app(argc, argv);
TranslationTest myObj;
QuickView view;
subthread object;
gpsthread obj;
gprsthread gprs;
view.rootContext()->setContextProperty("rootItem", (QObject *)&myObj);

    obj.start();
//from subthread
QObject::connect(&object, SIGNAL(batterytoqml(QVariant,QVariant)),item, SLOT(frombattery(QVariant,QVariant)));
QObject::connect(&gprs, SIGNAL(gprstoqml(QVariant)),item, SLOT(fromgprs(QVariant)));
return app.exec();

}

I have tried this as well

class gpsthread: public QThread{
    Q_OBJECT
private:nrega_status_t status2;

public:QTimer* t; 
explicit gpsthread(QObject *parent = 0):QThread(parent) {
    // QTimer *t = new QTimer(this);
    // connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
    // t->start(10000);
 }
 void run(){
    qDebug()<<"inside gps thread\n";
    t = new QTimer(this);
     connect(t, SIGNAL(timeout()), this, SLOT(processgps()));
     t->start(10000);
exec();    
}

public slots:void processgps(){
    int status2;
    status2=gps_management();
}
};

But it is giving error saying

 QObject: Cannot create children for a parent that is in a different thread

If I create object in constructor then also it will give the same error because the object will be created in the main thread. How to resolve this?

Inheriting from QThread is not the recommended usage. QThread is a complete class that runs an event loop, which is generally what you need. The documentation recommends using a worker object that inherits from QObject and does work in a slot. The worker is moved into a QThread. When a connected signal is sent, the slot will run in the correct thread.

class gpsworker: public QObject
{
Q_OBJECT
public:
    explicit gpsworker(QObject *parent = 0):
    QObject(parent)
    {}

public slots:
    void processgps() {
        qDebug() << "processgps()" << QThread::currentThreadId();
    }
}

void OwnerClass::startWorker() {
    QTimer *timer = new QTimer(this);
    QThread *thread = new QThread(this);
    this->worker = new gpsworker();
    this->worker->moveToThread(thread);
    connect(timer, SIGNAL(timeout()), this->worker, SLOT(processgps()) );
    connect(thread, SIGNAL(finished()), this->worker, SLOT(deleteLater()) );
    thread->start();
    timer->start();
}

If you want the timer to live in the other thread as well, QTimer::start is a slot.

QObject: Cannot create children for a parent that is in a different thready

is beacuse t = new QTimer(this) in the run() is creating an object in the child thread but this which point at gpsthread is in the main thread. A simple solution is t = new QTimer() without a parent and delete the timer in the destructor. Here is an example:

class gpsthread : public QThread {
    Q_OBJECT
public:
    explicit gpsthread(QObject *parent = 0):
        QThread(parent)
        ,timer(NULL) {
        qDebug() << "Parent thread" << QThread::currentThreadId();
    }
    ~gpsthread() {
        quit();
        wait();
        delete timer;
    }
protected:
    void run() {
        qDebug() << "Inside gps thread" << QThread::currentThreadId();
        timer = new QTimer;  // no parent
        connect(timer, SIGNAL(timeout()), this, SLOT(processgps()));
        timer->start(1000);
        exec();
    }

public slots:
    void processgps() {
        qDebug() << "processgps()" << QThread::currentThreadId();
    }

private:
    QTimer *timer;
};

Soon you will find out console print:

Parent thread 0x3b28
inside gps thread 0x3f10
processgps() 0x3b28
processgps() 0x3b28
processgps() 0x3b28
processgps() 0x3b28

which means processgps() is not working in your child thread. This is because this slot is a member of gpsthread which is in the main thread. A simple solution is call processgps() directly and use sleep() as timer:

class gpsthread : public QThread
{
    Q_OBJECT
public:
    explicit gpsthread(QObject *parent = 0):
        QThread(parent)
        , abort(false) {
        qDebug() << "Parent thread" << QThread::currentThreadId();
    }
    ~gpsthread() {
        abort = true;
        wait();
    }
protected:
    void run() {
        while(!abort) {
            sleep(1);
            processgps();
        }
    }
public slots:
    void processgps() {
        qDebug() << "processgps()" << QThread::currentThreadId();
    }
private:
    bool abort;
};

This is not a nice solution, a recommanded way is creating a worker to do all the job and then use QObject::moveToThread() as said in QThread Document

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM