Qt 多线程之线程事件循环(深入理解)

前言:

转载请附上连接,本帖原创请勿照抄。

Qt支持三种类型的信号-槽连接:
1,直接连接,当signal发射时,slot立即调用。此slot在发射signal的那个线程中被执行(不一定是接收对象生存的那个线程)
2,队列连接,当控制权回到对象属于的那个线程的事件循环时,slot被调用。此slot在接收对象生存的那个线程中被执行
3,自动连接(缺省),假如信号发射与接收者在同一个线程中,其行为如直接连接,否则,其行为如队列连接。

连接类型可能通过以向connect()传递参数来指定。注意的是,当发送者与接收者生存在不同的线程中,而事件循环正运行于接收者的线程中,使用直接连接是不安全的。同样的道理,调用生存在不同的线程中的对象的函数也是不是安全的。QObject::connect()本身是线程安全的。

直接连接和自动连接类似,大部分线程示例中发送信号都是此类。下面代码讲一下队列连接

参考代码:出处

下面通过while达成条件然后执行发送信号

signals:
    //对外通知网络反馈数据
    void response(const QByteArray& data);

    
while(!isInterruptionRequested())//调用requestInterruption()可退出线程
    {
        QThread::msleep(25);
        switch(m_state)
        {
        case E_Idle:
        {
            QThread::msleep(10);
            if(m_cmdQueue.length() > 0)
            {
                bool success = prepareNextCmd();
                if(success)
                    m_state =  E_Sending;
            }
        }break;
        case E_Sending:
        {
            qDebug()<<__LINE__<<__FUNCTION__<<"m_state =  E_Sending";
            QByteArray sendingData = m_currentCmd->getSendingData();
            m_tcpSocket->write(sendingData);
            qDebug()<<__LINE__<<__FUNCTION__<<"sendingData = "<<sendingData;
            m_tcpSocket->waitForReadyRead();
            m_state =  E_Reading;

        }break;
        case E_Reading:
        {
            qDebug()<<__LINE__<<__FUNCTION__<<"m_state =  E_Reading";
            QByteArray readData = m_tcpSocket->readAll();
            //信号response采用BlockingQueuedConnection方式与命令槽函数parseResponseData连接,
            //则当parseResponseData函数执行完毕之后,线程才会继续往后执行
            emit response(readData);
            m_currentCmd->deleteLater();
            m_state =  E_Idle;
        }break;
        default:{

        }
        }
    }

下面通过if达成条件然后绑定槽来接收线程返回的函数

bool TcpCmdExecThread::prepareNextCmd()
{
    if(m_cmdQueue.length() > 0){
        m_currentCmd = m_cmdQueue.takeFirst();
        connect(this,SIGNAL(response(QByteArray)),
                m_currentCmd,SLOT(parseResponseData(QByteArray)),Qt::BlockingQueuedConnection);
        return true;
    }
    return false;
}

qt信号与槽的五种连接方式:
1.默认连接:如果是在同一线程等价于直连,在不同线程等价于队列连接
2.直连:信号在哪,在哪个线程执行(最好只在同一线程中用)
3.队列连接: 槽在哪就在哪个线程执行 (槽函数不会立刻执行,等到接受者的当前执行的函数执行完才会执行槽函数)
4.阻塞队列连接: (槽函数调用时机和队列连接一样,只是会在发送者所在的线程会阻塞,直到槽函数运行完,发送者和接受者绝对不能在同一个线程)
5.Qt::UniqueConnect唯一连接,一个信号只能有一个槽连接,多个会失败可以使用|与以上四个结合使用

其它线程文章:

QT 初识线程(简单实现):https://blog.csdn.net/qq_37529913/article/details/110127940

QT QMutex使用详解:https://blog.csdn.net/qq_37529913/article/details/110187452

QT 线程之QSemaphore(深入理解):https://blog.csdn.net/qq_37529913/article/details/110187121

QT线程 Emit、Sgnals、Slot详细解释:https://blog.csdn.net/qq_37529913/article/details/110211435

QT 线程之QWaitCondition(深入理解):https://blog.csdn.net/qq_37529913/article/details/110212704

Qt 多线程之线程事件循环(深入理解):https://blog.csdn.net/qq_37529913/article/details/110229382

QT线程之QObjects(深入理解):https://blog.csdn.net/qq_37529913/article/details/110228837

QT线程之可重入与线程安全(深入理解):https://blog.csdn.net/qq_37529913/article/details/110224166

QT之浅拷贝、深拷贝、隐式共享(深度理解必看文章):https://blog.csdn.net/qq_37529913/article/details/110235596

QT 隐式共享机制对STL样式迭代器的影响:https://blog.csdn.net/qq_37529913/article/details/110252454

猜你喜欢

转载自blog.csdn.net/qq_37529913/article/details/110229382