我有一个派生自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(); ,则计时器按预期工作。但是,这对我来说似乎不对。
答案 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();
}