gpt4 book ai didi

c++ - QThread : Destroyed while thread is still running in QTest

转载 作者:行者123 更新时间:2023-12-03 13:15:50 26 4
gpt4 key购买 nike

我写了一个小的多线程消息队列。现在,我正在尝试进行测试。但是我遇到了无法解决的同步问题。
如果我删除了队列中的所有内容,则最小的可验证示例如下所示(抱歉,它有点大):

#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秒钟,并正确结束。但是,我得到:

WARNING: InOutQueueTest::limit15() Generate 19 numbers, starting at 517
Loc: [/home/juanjo/Trabajos/qml/test/inoutqueue.cpp(53)]
WARNING: InOutQueueTest::limit15() Generate 19 numbers, starting at 536
Loc: [/home/juanjo/Trabajos/qml/test/inoutqueue.cpp(53)]
QFATAL : InOutQueueTest::limit15() QThread: Destroyed while thread is still running
FAIL! : InOutQueueTest::limit15() Received a fatal error.
Loc: [Unknown file(0)]
Totals: 1 passed, 1 failed, 0 skipped, 0 blacklisted, 5068ms
********* Finished testing of InOutQueueTest *********
Aborted


应该结束测试(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”)。
    在QThread上调用exit()会立即返回,并且不会等待。并且deleteLater()在调用者的线程(不是目标线程)中执行,因此您不能指望它被称为“足够晚”。
    先执行exit(),然后执行wait(),然后执行deleteLater()

    关于c++ - QThread : Destroyed while thread is still running in QTest,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/66357998/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com