线程中的QTimer - 事件未处理?

时间:2010-07-30 17:38:51

标签: qt multithreading

我有一个派生自QThread的对象,类定义包含Q_OBJECT宏。我在线程中创建了一个计时器,所以我可以在线程运行时偶尔进行一些检查;但是,超时事件永远不会发生。

我也试过让计时器成为单一的,但没有发出任何事件。

默认情况下是否在线程中处理事件,还是需要执行其他操作才能处理事件?

以下是我如何设置线程和计时器的代码:

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(); 之前添加 QApplication :: processEvents(); ,则计时器按预期工作。但是,这对我来说似乎不对。

3 个答案:

答案 0 :(得分: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 = new Consumer();
...
QThread *thread = new QThread(this);
thread->start();
consumer->moveToThread(thread);

Consumer的所有子对象都将在线程Consumer被移动到的上下文中运行。可以为Consumer类创建超时信号,并将其与未在thread中运行的对象连接。一旦将对象移动到线程,Qt将确保将正确的信号/插槽类型应用于连接。

我遗漏了整个isRunning部分,因为我怀疑只要您只创建一个Consumer,您仍然需要它。

答案 1 :(得分:2)

除非您在其中显式创建事件循环,否则线程没有自己的事件循环。有关详细信息,请参阅http://doc.qt.io/qt-5/threads-qobject.html#per-thread-event-loop

答案 2 :(得分: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();
}