2014-02-05 2 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(); 
} 

내가 기대하는 것은 [... 보도] 핸들러 -> 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. 분명히 0이 아닙니다. (- 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 

#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에 Handler.cpp 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 

: 어쨌든 여기에 응용 프로그램 코드의 나머지 부분입니다

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

그냥 terminate() 슬롯을 사용하지 마십시오. 대신 quit을 사용하십시오. 종료시 스레드의 동작은 정의되지 않습니다. 특히 종료 된 스레드에 할당 된 데이터 (객체)가있는 경우에는 정의되지 않습니다. –

+0

의견을 주셔서 감사합니다. 불행히도 이것은 해결책이 아니었지만 종료 슬롯을 종료 슬롯으로 변경했습니다. 응용 프로그램은 여전히 ​​동일한 종료 코드를 사용하여 영원히 멈추지 만, 적어도 뭔가를 배웠습니다. – Wrath

+0

그리고 디버거에서 (코드 충돌이 발생한 위치) 디버거는 무엇이라고 말합니까? 어떤 컴파일러를 사용합니까? Btw, 당신은 소멸자에서 슬롯을 분리 할 필요가 없습니다. –

답변

1

내가 기대하는 것은 [... 보도] 핸들러 -> StartThread() 문 내 스레드의 시작에서 함수가 디버그 메시지를 기록하고 핸들러 내에서 내부 타이머가 완료되면 내가 좋은 라인을 얻을이며, 리턴 코드는 0입니다. 그러나 이것은 일어나지 않습니다.

당신의 완성 된 명령 프롬프트를받지 못하고있는 이유는 "[보도 ...]"때문에 QCoreApplication간부() 호출하는 것입니다. Qt docs state으로 : -

메인 이벤트 루프를 입력하고

그래서이라고합니다) (종료 될 때까지 기다립니다, 두 번째 스레드를 생성 한 일부 작업과 마무리 작업을 수행하도록 설정 , 주 스레드는 여전히 실행 중입니다. 주 스레드를 종료해야합니다.

그리고 응용 프로그램의 실행을 중지 할 때 물론, 리턴 코드는 다음과 같습니다 당신이 Ctrl + C "와 같은 뭔가 메인 스레드를 죽이는 것 같은 -1073741510

소리가 난다 ". 두 번째 스레드가 완료되어 정리 된 QCoreApplication :: exit()을 호출하면 여기에서 도움이됩니다.

+0

답변 해 주셔서 감사합니다. 그거였다. 정말로 로직이 완벽하게 작동하는 것 같습니다! – Wrath

관련 문제