2014-02-05 39 views
2

我在QT內部有線程問題。Qthread中的運行函數 - 應用程序將掛起

#include <QCoreApplication> 

#include "handler.hpp" 

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

    Handler* handler = new Handler(); 
    handler->StartThread(); 

    return a.exec(); 
} 

我想到的是,與handler-> StartThread()語句我線程啓動中的函數編寫調試消息,一旦處理程序中的內部定時器結束,我得到了很好的線[新聞...]和然後返回0的代碼。但是這沒有發生。我得到的是:

I WORK...   (0x1540) 
Worker has finished. (0x6f4 ) 
I WORK...   (0x1540) 
Worker has finished. (0x6f4 ) 
I WORK...   (0x1540) 
Worker has finished. (0x6f4 ) 
I WORK...   (0x1540) 
Worker has finished. (0x6f4 ) 
Thread stopped. 

當然,當我停止執行應用程序時,返回碼是:-1073741510。顯然不是那麼好的零。 反正這裏的應用程序代碼的其餘部分: Handler.hpp

#ifndef HANDLER_HPP 
#define HANDLER_HPP 

#include <QObject> 
#include <QThread> 
#include <QDebug> 
#include <QTimer> 

#include "testclass.hpp" 

class Handler : public QObject 
{ 
    Q_OBJECT 
public: 
    Handler(); 
    ~Handler(); 
    void StartThread(); 

public slots: 
    void functionFinished(); 
    void threadTerminated(); 

private: 
    QTimer*  shutdown; 
    QTimer*  timer; 
    QThread* thread; 
    MyClass* worker; 
}; 

#endif // HANDLER_HPP 

Handler.cpp

#include "handler.hpp" 

Handler::Handler() { 
    shutdown  = new QTimer(); 
    thread   = new QThread(); 
    timer   = new QTimer(); 
    worker   = new MyClass(); 

    worker->moveToThread(thread); 
    QObject::connect(thread, SIGNAL(started()), worker, SLOT(runAgain())); 
    QObject::connect(timer, SIGNAL(timeout()), worker, SLOT(runAgain())); 
    QObject::connect(worker, SIGNAL(iFinished()), this, SLOT(functionFinished())); 
    QObject::connect(shutdown, SIGNAL(timeout()), thread, SLOT(quit())); 
    QObject::connect(thread, SIGNAL(finished()), this, SLOT(threadTerminated())); 

    shutdown->start(20000); 
} 

Handler::~Handler() { 
    QObject::disconnect(thread, SIGNAL(started()), worker, SLOT(runAgain())); 
    QObject::disconnect(timer, SIGNAL(timeout()), worker, SLOT(runAgain())); 
    QObject::disconnect(worker, SIGNAL(iFinished()), this, SLOT(functionFinished())); 
    QObject::disconnect(shutdown, SIGNAL(timeout()), thread, SLOT(quit())); 
    QObject::disconnect(thread, SIGNAL(finished()), this, SLOT(threadTerminated())); 

    if (shutdown != 0) { 
     delete shutdown; 
     shutdown = 0; 
    } 

    if (timer != 0) { 
     delete timer; 
     timer = 0; 
    } 

    if (thread != 0) { 
     delete thread; 
     thread = 0; 
    } 

    if (worker != 0) { 
     delete worker; 
     worker = 0; 
    } 
} 

void Handler::functionFinished() { 
    qDebug() << "Worker has finished. (" << QThread::currentThreadId() << ")"; 
    timer->start(5000); 
} 

void Handler::threadTerminated() { 
    qDebug() << "Thread stopped."; 
} 

void Handler::StartThread() { 
    thread->start(); 
} 

MyClass的(頭 - testclass.hpp)

#ifndef TESTCLASS_HPP 
#define TESTCLASS_HPP 

#include <QTimer> 
#include <QObject> 

class MyClass : public QObject 
{ 
    Q_OBJECT 
public: 
    MyClass(); 

public slots: 
    void runAgain(); 

signals: 
    void iFinished(); 

private: 
    void doWork(); 

}; 

#endif // TESTCLASS_HPP 

MyClass的來源 - testclass.cpp

#include "testclass.hpp" 

#include <QThread> 
#include <QDebug> 

MyClass::MyClass() { 

} 

void MyClass::runAgain() { 
    doWork(); 
} 

void MyClass::doWork() { 
    qDebug() << "I WORK...\t(" << QThread::currentThreadId() << ")"; 
    emit iFinished(); 
} 

我previosly閱讀,它不是繼承的類一個好主意,一個線程內直接從QThread的跑了,所以我還是想出了這個解決方案,但它雖然它很好,但會變得腥。我願意接受任何建議,這是我第一次和QT一起學習,現在學習比以後感到抱歉更好。

哦,我的壞,我忘了具體的實際問題。爲什麼不執行以不錯的退出碼0結束?

+0

只是不要使用終止()插槽。改用quit。線程在終止期間的行爲是未定義的,特別是如果在終止的線程中有一些分配的數據(對象)。 –

+0

感謝您的評論。不幸的是,這不是解決方案,但我將終止插槽更改爲退出插槽。該應用仍然掛在永久性的相同的退出代碼,但至少我學到了一些東西。 – Wrath

+0

什麼調試器說(發生代碼崩潰的地方)?你使用什麼編譯器?順便說一句,你不需要斷開析構函數中的插槽。 –

回答

1

我想到的是,與handler-> StartThread()語句我線程啓動中的函數編寫調試消息,一旦處理程序中的內部定時器結束,我得到了很好的線[新聞...]和然後返回0的代碼。但是這不會發生。

你沒有得到的成品命令提示符的原因「[新聞...]」是由於QCoreApplication及其EXEC()調用。由於Qt docs state: -

進入主事件循環並等待退出()被調用

所以,你已經創建了第二個線程,將其設置做了一些工作,並完成,但主線程仍在運行。你需要退出主線程。

當然,當我停止應用程序的執行,返回碼:-1073741510

這聽起來像你的東西,如「Ctrl + C鍵查殺主線程」。調用QCoreApplication :: exit()當你的第二個線程完成並清理完畢後,應該在這裏幫助。

+0

感謝您的回答。就是這樣。真的,看起來邏輯完美! – Wrath