creating new thread using Qthread-Qt5

蹲街弑〆低调 提交于 2021-02-07 07:52:24

问题


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?


回答1:


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.




回答2:


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



来源:https://stackoverflow.com/questions/24776697/creating-new-thread-using-qthread-qt5

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!