2014-07-16 47 views
1

我正在尝试创建一个应该在后台运行的新线程gpsthread,并存储该值。使用Qthread-Qt5创建新线程

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(); 
} 
}; 

我的主课是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(); 

}

我曾经尝试这样做,以及

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(); 
} 
}; 

,但它给错误说

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

如果我在构造函数创建对象,然后也将会给相同的错误,因为该对象将在主线程中创建。 如何解决这个问题?

回答

3

继承QThread不是推荐用法。 QThread是一个完整的类,它运行一个事件循环,这通常是你需要的。 documentation建议使用从QObject继承的工作对象,并在插槽中工作。该工人被转移到QThread中。当发送连接的信号时,插槽将以正确的线程运行。

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(); 
} 

如果您希望定时器住在其他线程以及,QTimer::start是一个插槽。

+0

感谢解释这...这确实是使用线程的正确方法。 – Goddard

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

是怎么一回事,因为t = new QTimer(this)run()创造的子线程的对象,但其thisgpsthread是在主线程。一个简单的解决方案是没有父亲的t = new QTimer(),并在析构函数中删除计时器。这里有一个例子:

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; 
}; 

很快你会发现控制台打印:

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

这意味着processgps()没有在你的子线程的工作。这是因为此插槽是主线程中gpsthread的成员。一个简单的解决方法是直接调用processgps()和使用sleep()作为定时器:

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; 
}; 

这不是一个很好的解决方案,一个推荐方法是创建一个工人来完成所有的工作,然后用QObject::moveToThread()作为QThread Document