2017-02-09 1 views
1

QThread 내에서 QTimer을 사용하려고 시도했지만 QTimertimeout() 슬롯에 연결할 수 없습니다.QTimer가 제한 시간 슬롯을 호출하지 않습니다

내가 뭘 잘못하고 있니? 여기

내 코드입니다 : 모든

extern MainWindow *mainClass; 

class myObj : public QObject 
{ 
    Q_OBJECT 
public: 
    explicit myObj(QObject *parent = 0); 
    ~myObj(); 
    QThread workerThread; 

    int percent; 
    QTimer *percentTimer; 

public slots: 
    void doWork(); 
    void percentUpdate(); 
    void startFunction(); 

signals: 
    void start(); 
    void UpdateResult(); 
}; 

myObj::myObj(QObject *parent) : QObject(parent) 
{ 
    moveToThread(&workerThread); 

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater())); 
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult())); 
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork())); 
    connect(this, SIGNAL(start()), this, SLOT(startFunction())); 

    percent++; 
    percentTimer = new QTimer(); 
    percentTimer->moveToThread(&workerThread); 
    percentTimer->setInterval(1000); 
    connect(percentTimer, SIGNAL(timeout()), this,SLOT(percentUpdate())); 

} 

myObj::~myObj() { 
    workerThread.quit(); 
    workerThread.wait(); 
    if (percentTimer) percentTimer->deleteLater(); 
} 

void myObj::doWork() 
{ 
    emit start(); 
    workerThread.exec();  
} 

void myObj::startFunction() 
{ 
    percentTimer->start(); 
    QThread::sleep(60); 
    percentTimer->stop();  
} 

void myObj::percentUpdate() 
{ 
    qDebug() << "In Timer" << percent++; 
    emit UpdateResult(); 

} 
+0

디버거에서이 단계를 수행하면 어떻게됩니까? 먼저 각 메소드에 중단 점을 넣습니다. 어떤 사람이 어떤 순서로 부름 받았습니까? – MrEricSir

+0

슬롯 percentUpdate를 제외하고는 모든 것이 잘 작동합니다. timeout @MrEricSir에서 호출되지 않습니다. –

+0

@MrEricSir,'percentTimer-> moveToThread (...); '앞에 connect (percentTimer ...)를 시도하십시오. –

답변

1

첫째, 당신은 슬롯이되지 않을 것 가능성이 start 신호에 연결되어 있기 때문에 그 상황에서 myObj 작업 (필요한 연결을 생성 후 을 시작할 수 있도록 workerThread을 shart한다 달리 실행). 대신 QThread::sleepFor를 사용하는이 같은 것을 사용해야합니다 QThread::sleepFor이 전체 스레드 실행을 정지하기 때문에

QEventLoop loop; 
QTimer::singleShot(60000, &loop, SLOT(exit())); 
loop.exec(); 

는 지연을 만들 수 있습니다. 따라서이 스레드에 연결된 이벤트는 처리되지 않습니다.

workerThread.exec()은 유용하지 않습니다.

+0

감사합니다 works (y) @RealFresh –

4

QTimer를 작성한 스레드와 다른 스레드에서 시작하려고하기 때문입니다. QTimer와 쓰레드를 사용할 때, QTimer를 제어 할 쓰레드에 QTimer를 생성 할 때 매우 신중해야합니다. QTimer class documentation에서

: 다중 스레드 응용 프로그램에서

, 당신은 이벤트 루프가있는 모든 스레드에서 QTimer를 사용할 수 있습니다. GUI가 아닌 스레드에서 이벤트 루프를 시작하려면 QThread :: exec()를 사용하십시오. Qt는 타이머의 스레드 선호도를 사용하여 timeout() 신호를 내보낼 스레드를 결정합니다. 이 때문에 스레드의 타이머를 시작하고 중지해야합니다 (). 다른 스레드에서 타이머를 시작할 수 없습니다. 당신의 doWorkstart 신호가 workerThread에서 방출하는 동안 귀하의 경우 percentTimer = new QTimer();

는, (이 여전히 그것을 실행하는 메인 쓰레드되기 전에 moveToThread를 사용하더라도) 메인 스레드에서 실행됩니다.

당신은 예를 들어 할 수있는 new QTimer 오히려 생성자보다 당신의 workerThread에서 호출 void init() 슬롯에서의 QTimer 만들고 적절한 스레드에 의해 소유되어 있는지 확인합니다.

myObj::myObj(QObject *parent) : QObject(parent), percentTimer(nullptr) 
{ 
    moveToThread(&workerThread); 

    connect(&workerThread, SIGNAL(finished()), this, SLOT(deleteLater())); 
    connect(this, SIGNAL(UpdateResult()), mainClass, SLOT(on_UpdateResult())); 
    connect(&workerThread, SIGNAL(started()), this, SLOT(init())); 
    connect(&workerThread, SIGNAL(started()), this, SLOT(doWork())); 
    connect(this, SIGNAL(start()), this, SLOT(startFunction())); 

    percent++; 
} 

void myObj::init() { 
    percentTimer = new QTimer(); 
    percentTimer->setInterval(1000); 
    connect(percentTimer, SIGNAL(timeout()), this, SLOT(percentUpdate())); 
} 
관련 문제