QThread:在线程仍在QTest中运行时销毁

创伤

我写了一个小的多线程消息队列。现在,我正在尝试进行测试。但是我遇到了无法解决的同步问题。

如果我删除了队列中的所有内容,则最小的可验证示例如下所示(抱歉,它有点大):

#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( );
}

我只是停止两个计时器。

  • 我究竟做错了什么 ?

  • 我该如何解决?

ypnos

您需要始终wait()在线程上将其删除(非Qt说“ join”)。

调用exit()QThread会立即返回,并且不会等待。并且deleteLater()在调用者的线程(不是目标线程)中执行,因此您不能指望它被称为“足够晚”。

待办事项exit(),然后wait(),然后deleteLater()

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

QThread 在线程仍在运行时被销毁

退出时“ QThread:线程仍在运行时被销毁”

PyQt QThread:线程仍在运行时被销毁

PySide2 QThread错误:QThread:线程仍在运行时被销毁

PyQt5-QThread:线程仍在运行时被销毁

PYQt5:QThread:线程仍在运行时销毁(实例分配为 QDialog )

从Windows cmd或IDLE而不是从PyCharm运行时出现“ QThread:线程仍在运行时销毁”的问题?

QThread:线程仍在运行时被破坏了吗?

PyQt5:线程仍在运行时被销毁

Qt:在关闭期间线程仍在运行时,qthread被破坏

当主线程仍在python中运行时,如何使用线程获取实时用户输入

QWaitCondition:在线程仍在等待时被销毁

在线判断中的运行时错误

为什么某些语句在线程中运行时无法执行?

如何在线程化Java应用程序中的运行时确定主类?

Java:在线程内运行时 JNDI 查找失败

QProcess:进程(Web浏览器)仍在运行时被销毁

Qt避免警告'QProcess:在进程仍在运行时销毁

PySide:线程销毁后仍在运行

如何限制线程的执行时间并在线程运行时间过长时终止该线程?

C#-在创建新控件的线程仍在运行时关闭表单

如何在主线程仍在运行时使用线程运行另一个 JFrame

Qt QThread运行时立即失败

PyQt对话框在线程运行时不负责

为什么 JButton 在线程运行时不起作用?

在VM中运行时,Swing遇到线程同步问题

在Eclipse中运行时,Linux线程被实时信号挂起

多线程导致Qt中的运行时错误

在进程仍在运行时在SwiftUI中更新文本