2014-07-16 45 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