2010-07-30 4 views
2

QThread에서 파생 된 개체가 있고 클래스 정의에 Q_OBJECT 매크로가 포함되어 있습니다. 스레드가 실행되는 동안 몇 가지 가끔 검사를 할 수 있도록 스레드 내에 타이머를 만들었습니다. 그러나 timeout 이벤트는 절대로 발생하지 않습니다.스레드의 QTimer - 이벤트가 처리되지 않습니까?

타이머를 하나만 만들려고했지만 이벤트가 방출되지 않았습니다.

이벤트는 기본적으로 스레드에서 처리됩니까? 아니면 처리되도록하려면 다른 작업을 수행해야합니까? 여기

내가 스레드 및 타이머 설정 방법에 대한 코드입니다 : 내가 의 QApplication :: processEvents를 추가하는 경우

void MyClass::run(void) 
{ 
    checkTimer_chA = new QTimer(this); 

    qDebug() << connect(checkTimer_chA, SIGNAL(timeout()), this, SLOT(timerExpiry_chA())); 

    checkTimer_chA->start(1000); 

    // prevent multiple, simultaneous starts 
    if(!isRunning) 
    { 
     qDebug() << "Thread: MyClass::run"; 
     isRunning = true; 

     while(isRunning) 
     { 
      getData(); 
      processData(); 
      yieldCurrentThread(); 
     } 
    } 

    checkTimer_chA->stop(); 

    delete checkTimer_chA; 
} 


void DAQ::timerExpiry_chA(void) 
{ 
    qDebug() << "timerExpiry_chA"; 
    checkTimer_chA->stop(); 
} 

를(); 에 대한 호출 바로 전에 yieldCurrentThread(); 타이머가 예상대로 작동합니다. 그러나 이것은 나에게 잘못된 것처럼 보인다.

+0

스레드 코셔에서 QApplication :: processEvents()를 호출합니까? exec()가 배후에서 무엇을 할 것인가. – dwj

답변

1

아마도 스레드에서 실행중인 이벤트 루프가 필요합니다. 코드를 다음과 같이 변경하는 것은 어떻습니까?

void MyClass::run(void) 
{ 
    checkTimer_chA = new QTimer(this); 

    qDebug() << connect(checkTimer_chA, SIGNAL(timeout()), this, SLOT(timerExpiry_chA())); 

    checkTimer_chA->start(1000); 

    // prevent multiple, simultaneous starts 
    if(!isRunning) 
    { 
     qDebug() << "Thread: MyClass::run"; 
     isRunning = true; 

     QTimer::singleShot(0, this, SLOT(process())); 
     exec(); 
    } 

    checkTimer_chA->stop(); 

    delete checkTimer_chA; 
} 

void MyClass::process() 
{ 
    if(isRunning) 
    { 
     getData(); 
     processData(); 
     yieldCurrentThread(); 
     QTimer::singleShot(0, this, SLOT(process())); 
    } 
    else 
     QThread::exit(); 
} 

void MyClass::timerExpiry_chA(void) 
{ 
    qDebug() << "timerExpiry_chA"; 
    checkTimer_chA->stop(); 
} 
+0

process()가 호출되면 스레드가 이벤트 루프로 돌아갈 기회를 얻지 못하기 때문에 아마 작동하지 않을 것입니다. –

+0

아마도 당신 말이 맞을 것입니다. 코드가 불완전합니다. yieldCurrentThread()가 무엇을하는지는 알 수 없습니다. 이벤트 루프를 실행할 수 없다고 가정 해 봅시다. 위의 코드를 이벤트 루프로 되돌리려면 위의 코드를 변경했습니다. – baysmith

+0

yieldCurrentThread()는 Qt 호출입니다. - http://doc.trolltech.com/4.6/qthread.html#yieldCurrentThread – dwj

6

Qt에서 스레드로 작업하는 것은 때로는 약간의 번거 로움이 될 수 있습니다. This 블로그 게시물은 나에게 진정한 눈이었습니다. 블로그 게시물에 제안 된 스타일을 문제에 적용하는 경우 다음과 같은 해결책을 얻게됩니다. 다음과 같이

Consumer::Consumer(): 
    checkTimer_(new QTimer(this)) 
{ 
    QObject::connect(checkTimer_, SIGNAL(timeout()), this, SLOT(onTimerExpiration()); 
    QObject::connect(this, SIGNAL(ready()), this, SLOT(consume()); 
} 

bool Consumer::event(QEvent *e) 
{ 
    if (e->type() == QEvent::ThreadChange) 
    { 
     QTimer::singleShot(0, this, SLOT(start()); 
    } 

    return QObject::event(e); 
} 

void Consumer::consume() 
{ 
    getData(); 
    processData(); 
    emit ready(); 
} 

void Consumer::start() 
{ 
    checkTimer_->start(1000); 
    emit ready(); 
} 

void Consumer::onTimerExpiration() 
{ 
    qDebug() << "timeout"; 
} 

그런 다음 별도의 스레드에서 실행 : Consumer

... 
Consumer *consumer = new Consumer(); 
... 
QThread *thread = new QThread(this); 
thread->start(); 
consumer->moveToThread(thread); 

모든 자식 개체가 이동 된 스레드 Consumer의 컨텍스트에서 실행됩니다. Consumer 클래스에 대한 시간 초과 신호를 만들고 thread에서 실행되지 않는 개체와 연결할 수 있습니다. Qt는 객체가 스레드로 옮겨지면 적절한 신호/슬롯 유형이 연결에 적용되도록합니다.

내가만 만들면 당신은 여전히 ​​그것을 필요로 할 것이므로, 전체 isRunning 부분을 생략했습니다.

관련 문제