【问题标题】:Communication with QThread not working with Signals / Slots与 QThread 的通信不适用于信号/插槽
【发布时间】:2014-05-08 21:32:05
【问题描述】:

我为QThreads 关注了本教程: http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

我遇到的唯一问题是杀死QThread。我在工作对象的process() 循环中有一个标志,我将它推入我的QThread 实例,称为m_ShouldSendFrames。如果该标志被翻转为 false,那么我的处理循环会中断,并且工作对象会发出 finished() 信号。

我遇到的问题是我似乎无法让QThread 中的工作对象从主线程接收我的stopSendingFrames() 信号。我像这样连接它(并且连接返回 'true' ):

connect(this, SIGNAL(stopSendingFrames()), m_UdpWorkerBlended, SLOT(stopFrames()),Qt::QueuedConnection); // Stop broadcasting

在我的killUdpThread 函数中,我想发出stopSendingFrames() 信号并让m_UdpWorker 对象得到它。但它永远不会!我可以更改该标志的唯一方法是在 killUdpThread 中执行此操作:

m_UdpWorkerBlended->stopFrames();

然而,这是不安全的并且随机崩溃,因为它不是从工作人员正在运行的QThread 调用的。

我也尝试过 invokeMethod 方式 - 但它也不会触发插槽:

QMetaObject::invokeMethod(m_UdpWorkerBlended,"stopFrames",Qt::QueuedConnection);

有人可以帮我理解为什么我不能调用invokeMethod 或使用信号来触发我在QThread 的worker 对象中运行的插槽,但我可以直接调用它(不安全)?谢谢!

启动线程函数:

int UdpThreadController::startUdpThread(int frameType, int port, QString ip) {

    #if SINGLETON_CAMERA_UDP_DEBUG
    qDebug() << "Starting Thread! Frame type is: " << frameType;
    #endif

    // Check for type of frame to emit
    if ( frameType == 0 ) {

        #if SINGLETON_CAMERA_UDP_DEBUG
        qDebug() << "Frames are vl";
        #endif

        // Delete any existing threads / workers
        killUdpThread(0);

        // New objects
        m_UdpThreadBlended = new QThread();
        m_UdpWorkerBlended = new UdpWorker();

        // Assign Port and IP and Frame Type
        m_UdpWorkerBlended->m_ShouldSendFrames = true;
        m_UdpWorkerBlended->m_Port = port;
        m_UdpWorkerBlended->m_AddressToUse = ip;
        m_UdpWorkerBlended->m_FrameType = frameType;

        // Push into thread
        m_UdpWorkerBlended->moveToThread(m_UdpThreadBlended);

        // Connect signals
        connect(this, SIGNAL(stopSendingFrames()), m_UdpWorkerBlended, SLOT(stopFrames()),Qt::QueuedConnection); // Stop broadcasting
        connect(m_UdpThreadBlended, SIGNAL(started()), m_UdpWorkerBlended, SLOT(process()));
        connect(m_UdpWorkerBlended, SIGNAL(finished()), m_UdpThreadBlended, SLOT(quit()));
        connect(m_UdpWorkerBlended, SIGNAL(finished()), m_UdpWorkerBlended, SLOT(deleteLater()));
        connect(m_UdpThreadBlended, SIGNAL(finished()), m_UdpThreadBlended, SLOT(deleteLater()));
        m_UdpThreadBlended->start();

        // All done
        return 0;

杀死线程函数:

int UdpThreadController::killUdpThread(int frameType) {

    #if SINGLETON_CAMERA_UDP_DEBUG
    qDebug() << "Killing Thread! Frame type is: " << frameType;
    #endif

    // Check for type of frame to emit
    if ( frameType == 0 ) {

        // Delete any existing threads / workers
        if ( m_UdpWorkerBlended ) {

            #if SINGLETON_CAMERA_UDP_DEBUG
            qDebug() << "Emit signal to kill thread...";
            #endif

            // Stop broadcasting
            m_UdpWorkerBlended->stopFrames();

        }

        #if SINGLETON_CAMERA_UDP_DEBUG
        qDebug() << "Success ending UDP...";
        #endif

        // All done
        return 0;

    }

【问题讨论】:

  • 你能分享你发出stopSendingFrames信号的代码吗?
  • 嗨,所以在清单末尾的 killUdpThread 函数中,我尝试发出信号 stopSendingFrames 来代替 m_UdpWorkerBlended->stopFrames()。我将清单中的行替换为:“emit stopSendingFrames()”。工作对象从未收到信号。
  • 当您尝试发出信号时,工作线程“忙”吗?只有在线程空闲时才能传递信号。另外,您是否考虑过使用&lt;QtConcurrentRun&gt; 代替线程?我发现它更方便。
  • 您的UdpWorker 中不会碰巧有某种无限循环吗?

标签: c++ qt signals-slots qthread qobject


【解决方案1】:

感谢您的意见。我通过一个单例解决了这个问题,该单例具有一个标志,即 QThread 中我的工作对象中的处理循环读取每个循环迭代。它受到 QReadWrite 锁的保护。

int UdpThreadController::killUdpThread(int frameType) {

    #if SINGLETON_CAMERA_UDP_DEBUG
    qDebug() << "Killing Thread! Frame type is: " << frameType;
    #endif

    // Check for type of frame to emit
    if ( frameType == 0 ) {

        // Delete any existing threads / workers
        if ( m_UdpWorkerBlended ) {

            #if SINGLETON_CAMERA_UDP_DEBUG
            qDebug() << "Setting flag to kill thread...";
            #endif

            // Stop broadcasting
            m_Lock.lockForWrite();
            m_ShouldSendFramesBlended = false;
            m_Lock.unlock();

        }

        #if SINGLETON_CAMERA_UDP_DEBUG
        qDebug() << "Success ending Blended UDP...";
        #endif

        // All done
        return 0;

bool UdpThreadController::shouldContinueSendingFrames(int frameType) {

    #if SINGLETON_CAMERA_UDP_DEBUG
    qDebug() << "Checking if we should continue processing: " << frameType;
    #endif

    // Check for type of frame to emit
    if ( frameType == 0 ) {

        m_Lock.lockForRead();
        #if SINGLETON_CAMERA_UDP_DEBUG
        qDebug() << "Should continue Blended: " << m_ShouldSendFramesBlended;
        #endif
        bool shouldBroadcast = m_ShouldSendFramesBlended;
        m_Lock.unlock();

        // All done
        return shouldBroadcast;

    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-18
    • 1970-01-01
    • 2011-12-14
    • 1970-01-01
    • 2012-09-11
    相关资源
    最近更新 更多