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

dwj*_*dwj 2 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();
}
Run Code Online (Sandbox Code Playgroud)

如果我添加QApplication :: processEvents(); 就在调用yieldCurrentThread()之前; 计时器按预期工作.但是,这对我来说似乎不对.

Ton*_*vel 6

在Qt中使用线程有时会有点麻烦.这篇博文对我来说真的让人大开眼界.如果我们采用博客文章中提出的风格来解决您的问题,我们最终会得到如下解决方案.

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";
}
Run Code Online (Sandbox Code Playgroud)

然后在一个单独的线程中运行它,如下所示:

...
Consumer *consumer = new Consumer();
...
QThread *thread = new QThread(this);
thread->start();
consumer->moveToThread(thread);
Run Code Online (Sandbox Code Playgroud)

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

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