我写了一个小的多线程消息队列。现在,我正在尝试进行测试。但是我遇到了无法解决的同步问题。
如果我删除了队列中的所有内容,则最小的可验证示例如下所示(抱歉,它有点大):
#include <QCoreApplication>
#include <QDebug>
#include <QTimer>
#include <QtTest/QtTest>
#include <random>
#include <thread>
static std::vector< int > dummy;
class Writer : public QObject {
Q_OBJECT
public:
Writer( QObject *parent = nullptr ) : QObject( parent ) { }
Writer( unsigned, QObject *parent = nullptr ) : QObject( parent ) { }
public:
const std::vector< int > &beginPendings( ) { return dummy; }
void endPendings( ) { }
Q_SIGNALS:
void haveEvents( );
public Q_SLOTS:
void start( ) {
m_stop.test_and_set( );
connect( &m_inputTimer, &QTimer::timeout, this, &Writer::onTimer );
m_inputTimer.start( 100U );
connect( &m_outputTimer, &QTimer::timeout, this, &Writer::notifyEvents );
m_outputTimer.start( 250U );
}
void stop( ) {
m_inputTimer.stop( );
m_outputTimer.stop( );
}
private Q_SLOTS:
void onTimer( ) {
int limit = dist( mt );
for( int idx = 0; idx < limit; ++idx ) {
++m_idx;
}
}
void notifyEvents( ) {
emit haveEvents( );
}
private:
QTimer m_inputTimer;
QTimer m_outputTimer;
int m_idx = 0;
std::atomic_flag m_stop = ATOMIC_FLAG_INIT;
std::random_device rd;
std::mt19937 mt{ rd( ) };
std::uniform_int_distribution< int > dist{ 1, 20 };
};
class InOutQueueTest: public QObject {
Q_OBJECT
public Q_SLOTS:
void onPendingEvents( void ) {
writer->endPendings( );
}
void onTimeout( ) {
writer->stop( );
backendThread->exit( 0 );
backendThread->deleteLater( );
stop = true;
}
private Q_SLOTS:
void limit15( ) {
finishTimer.setSingleShot( true );
finishTimer.start( 5000 );
backendThread = new QThread( );
writer = new Writer( 15U );
connect( &finishTimer, &QTimer::timeout, this, &InOutQueueTest::onTimeout );
connect( writer, &Writer::haveEvents, this, &InOutQueueTest::onPendingEvents );
writer->moveToThread( backendThread );
backendThread->start( );
writer->start( );
while( !stop ) {
QCoreApplication::processEvents( );
}
}
private:
Writer *writer;
QThread *backendThread;
int last = 0;
QTimer finishTimer;
bool stop = false;
};
QTEST_GUILESS_MAIN( InOutQueueTest )
#include "inoutqueue.moc"
我希望测试能持续5秒钟,并正确结束。但是,我得到:
警告:InOutQueueTest :: limit15()生成19个数字,从517开始位置
:[/home
/juanjo/Trabajos/qml/test/inoutqueue.cpp( 53)]警告:InOutQueueTest :: limit15()生成从19开始的数字536位置
:[/ home / juanjo / Trabajos / qml / test / inoutqueue.cpp(53)]
QFATAL : InOutQueueTest::limit15() QThread: Destroyed while thread is still running
失败!:InOutQueueTest :: limit15()收到致命错误。
位置:[未知文件(0)]
总计:1个通过,1个失败,0个被跳过,0个被列入黑名单,5068ms
********* InOutQueueTest测试完成*********
中止
该代码应结束测试(5秒以后)是这样的:
void onTimeout( ) {
writer->stop( );
backendThread->exit( 0 );
backendThread->deleteLater( );
stop = true;
}
我stop( )
在Writer
中调用该exit( )
方法,在辅助线程中调用该方法,然后在事件循环的下一次迭代中将其删除(这是理论上的)。
在Writer
类中,stop( )
方法也是:
void stop( ) {
m_inputTimer.stop( );
m_outputTimer.stop( );
}
我只是停止两个计时器。
我究竟做错了什么 ?
我该如何解决?
您需要始终wait()
在线程上将其删除(非Qt说“ join”)。
调用exit()
QThread会立即返回,并且不会等待。并且deleteLater()
在调用者的线程(不是目标线程)中执行,因此您不能指望它被称为“足够晚”。
待办事项exit()
,然后wait()
,然后deleteLater()
。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句