Qtマルチスレッドメカニズムを使用して、デュアルシリアルデータストリームの送受信を実現します

前回の記事に基づいて、2つのシリアルポートから同時にデータを送受信できるダイアログボックスプログラムを作成しました。各シリアルポートは個別のサブスレッドに実装されています。編集をクリアするボタンを追加しました。

1メインプログラムインターフェイス

ここに写真の説明を挿入

2 2つの子スレッドのスレッド番号(デバッグ情報に出力)

ここに写真の説明を挿入
メインスレッドのID番号は0x179cです。2つのシリアルポートサブスレッドクラスがメインスレッドで構築されます。シリアルポートは、それぞれのサブスレッドでデータを開始および受信します。サブスレッドID番号は0x14e4および0x5b0です。シリアルポートの閉鎖はメインスレッドにあります。これは、接続構成に関連しています。コードは次のように表示されます。

#include "serialcontroller.h"
#include <QDebug>

SerialController::SerialController(QObject *parent) : QObject(parent)
{
    
    
    m_portId = -1;
}

SerialController::~SerialController()
{
    
    
    if(m_serialThread.isRunning())
    {
    
    
        m_serialPort->closePort();
        delete m_serialPort;
        m_serialThread.quit();
        m_serialThread.wait();
     }

}
void SerialController::initCtrl(int portId,QString portName,long portBaud)
{
    
    
    m_portId = portId;
    m_portName = portName;
    m_portBaud = portBaud;
    qDebug()<<"Controller is running in main thread: "<<QThread::currentThreadId();

    //实例对象保存在堆上,没有父对象的指针要想正常销毁,需要将线程的 finished() 信号关联到 QObject 的 deleteLater() 让其在正确的时机被销毁

    m_serialPort = new SerialPort(m_portId,m_portName,m_portBaud);
    //m_serialPort对象不能有父对象。
    m_serialPort->moveToThread(&m_serialThread);

    connect(this,&SerialController::startRunning,m_serialPort,&SerialPort::startPort);
    connect(&m_serialThread,&QThread::finished,m_serialPort,&QObject::deleteLater);
    connect(this,&SerialController::ctrlSendData,m_serialPort,&SerialPort::write_Data);//从主线程发来的数据写入串口
    connect(m_serialPort,&SerialPort::receive_data,this,&SerialController::ctrlReceiveData);//从串口读取的数据发送给主线程
}
void SerialController::startCtrl()
{
    
    
    m_serialThread.start();
    emit startRunning();

}
void SerialController::stopCtrl()
{
    
    
    if(m_serialThread.isRunning())
    {
    
           
        m_serialPort->closePort();
        m_serialThread.quit();//会自动发送finished信号
        m_serialThread.wait();       
    }
}

シリアルポートが開始してデータを受信する関数startPortは、QThreadクラスの接続信号に関連付けられているため、子スレッドで実行されます。シリアルポートのclose関数closePortは、スロット関数ではなく接続に関連付けられていませんが、SerialControllerクラスのstopCtrlで実行されます。 SerialControllerはメインスレッドに存在するため、closePortはメインスレッドで実行されます。
したがって、検証の前の記事の要点(3)は次のとおりです。
(3)コントローラーオブジェクトとワーカーオブジェクトはどのスレッドにありますか?「あなたがそれを作成する場所はあなたが属する場所に属する」というフレーズはどこにでも当てはまります。moveToThread()関数は、指定されたスレッドでスロット関数を呼び出すことです。つまり、コントローラーオブジェクトとワーカーオブジェクトはメインスレッドにあります。接続にバインドされたスロット関数(およびスロット関数本体によって呼び出される関数)に加えて、残りのワーカー関数もメインスレッドで実行されます。この接続の送信者は、SerialController自体(this)またはm_serialThreadです。
moveToThread()は、ワーカーオブジェクト全体をコントローラースレッドに「移動」しませんが、実行のためにスロット関数をコントローラースレッドに接続します。これに注意を払わないと、「QObject ::別のスレッドにある親の子を作成できない」という問題が発生する可能性があります。または、「時間のかかる作業コード」がまだメインスレッドで実行されています。

おすすめ

転載: blog.csdn.net/SmartTiger_CSL/article/details/104383717