2014-10-14 3 views
1

그래, QTimer에서 완전히 잃어 버렸어. 문제는 다음과 같습니다. 다중 스레드 응용 프로그램이 있으며 QTimer의 시간 초과 작업이 필요합니다. 나는 이렇게했다 :QTimer in multithreaded application

QTimer* timer = new QTimer(); 
timer->setSingleShot(true); 
connect(timer, SIGNAL(timeout()), someObject, SLOT(work())); 

그리고 이것은 작동하지 않았다. 가끔 work()가 전혀 호출되지 않았고, 프로그램을 닫을 때 호출되는 경우가 있었으며, 때로는 모두 정상적으로 보였습니다.
그래서 타이머에 스레드가 필요하다는 생각이 들었습니다. MCV 예를 들면 :

class Tester : public QObject 
{ 
Q_OBJECT 
public: 
Tester(QObject* par = 0) : QObject(par) 
{ 
} 
public slots: 
void greet() 
{ 
    qDebug()<<"hello"; 
} 
}; 

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

QTimer* timer1 = new QTimer(); 

QThread* thread = new QThread(); 
Tester* tester = new Tester(); 

timer1->setInterval(500); 
timer1->setSingleShot(false); 
timer1->moveToThread(thread); 


QObject::connect(thread, SIGNAL(started()), timer1, SLOT(start())); 

QObject::connect(timer1, SIGNAL(timeout()), tester, SLOT(greet())); 

QObject::connect(timer1, SIGNAL(timeout()), timer1, SLOT(deleteLater())); 
QObject::connect(timer1, SIGNAL(destroyed()), thread, SLOT(quit())); 

thread->start(); 

thread->wait(); 

delete thread; 
delete tester; 

return a.exec(); 
} 

그리고이 예제는 아무 것도하지 않습니다. 그것은 나에게 인사하지 않기 때문에 시간 제한은 호출되지 않으며 종료되지 않으므로 스레드가 중지되지 않습니다. 질문은 다음과 같습니다.
1.이 코드의 문제점은 무엇입니까?
2. 멀티 스레드 환경에서 QTimer를 올바르게 사용하는 방법은 무엇입니까?

답변

7

QTimer::setInterval을 호출하면 QTimer가 시작되지 않습니다. 그것은 단지 QTimer::timeout 신호가 방출되는 간격을 설정합니다. QTimer를 시작하지 않았습니다. QTimer::start을 사용하십시오.

여기 여러 실수를하고 있다고 생각합니다. 모든 연결이 완료되면 타이머를 스레드로 이동해야합니다. 타이머가 한 스레드에 있고 스레드 개체가 다른 스레드에 있기 때문에 스레드가 시작될 때 타이머를 시작하는 것이 얼마나 안전 할 지 모릅니다. QTimer은 생성 된 동일한 스레드에서 시작해야합니다. QThread 개체는 스레드 처리기이며 생성 된 스레드에 있습니다. 나는 당신의 예에 수행 된 수정 사항을 참조하십시오

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

//#include "tester.h" 

class Tester : public QObject 
{ 
    Q_OBJECT 

public: 
    Tester(QObject* par = 0) : QObject(par) 
    { 
    } 

public slots: 
    void greet() 
    { 
     qDebug()<<"hello"; 
    } 
}; 

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

    QTimer* timer1 = new QTimer(); 

    QThread* thread = new QThread(); 
    Tester* tester = new Tester(); 

    timer1->setInterval(500); 
    timer1->setSingleShot(false); 
    timer1->start(); 

    QObject::connect(timer1, SIGNAL(timeout()), tester, SLOT(greet())); 

    timer1->moveToThread(thread); 

    thread->start(); 

    return a.exec(); 
} 

그것은 내가, 당신이 만들 수있는 예를 희망, 그것이 가장 안전한/최선의 수정 (메모리 누수 및 기타)은 아니지만.

이 내 의견 오른쪽에있을 것입니다 및 메모리없이에 QTimer를 사용하는 방법을 누수 다른 QThread :

handler.h

#ifndef HANDLER_H 
#define HANDLER_H 

#include <QObject> 

class QTimer; 
class QThread; 
class Tester; 

class Handler : public QObject 
{ 
    Q_OBJECT 

public: 
    explicit Handler(QObject *parent = 0); 
    ~Handler(); 

    void exec(); 

private: 
    QTimer* timer; 
    QThread* thread; 
    Tester* tester; 
}; 

#endif // HANDLER_H 

handler.cpp

#include "handler.h" 
#include "tester.h" 

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

Handler::Handler(QObject *parent) : 
    QObject(parent) 
{ 
    timer = new QTimer; 
    thread = new QThread(this); 
    tester = new Tester(this); 

    timer->setInterval(500); 
    timer->setSingleShot(false); 

    QObject::connect(timer, SIGNAL(timeout()), tester, SLOT(greet())); 
    QObject::connect(thread, SIGNAL(destroyed()), timer, SLOT(deleteLater())); 
} 

Handler::~Handler() 
{ 
    thread->wait(); 
} 

void Handler::exec() 
{ 
    timer->start(); 

    timer->moveToThread(thread); 

    thread->start(); 
} 

tester.h

#ifndef TESTER_H 
#define TESTER_H 

#include <QObject> 

class Tester : public QObject 
{ 
    Q_OBJECT 

public: 
    Tester(QObject* par = 0); 

public slots: 
    void greet(); 
}; 


#endif // TESTER_H 

tester.cpp

#include "tester.h" 

#include <QDebug> 

Tester::Tester(QObject *parent) : 
    QObject(parent) 
{ 
} 

void Tester::greet() 
{ 
    qDebug()<<"hello"; 
} 

MAIN.CPP는

#include <QCoreApplication> 

#include "handler.h" 

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

    Handler handler; 
    handler.exec(); 

    return a.exec(); 
} 
+0

신중 QObject를이 : ((스레드, SIGNAL (시작 연결 코드를 읽어 보시기 바랍니다)), timer1, SLOT (start())); 아니면 내가 틀렸어? – DoctorMoisha

+0

@DoctorMoisha 네 말이 맞아. 내 편집 내용을 확인하십시오. – Iuliu

+0

감사합니다.하지만 메모리 누수를 방지하기 위해 어떻게해야합니까? – DoctorMoisha