Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

same serial in multiple threads giving error



  • Hi,

    I am facing some issue in qt serial multi threading. I have tested my code with different serial port and it is working fine. But in my actual application I need to use Same serial terminal in different threads. Using the first thread I am able to communicate with the device, but when the second thread will come that time the "Serial port not open" error is coming. Why the same serial in multi threading is not working?
    I am attaching my thread code below,

    #include "masterthread.h"
    #include <QTime>
    #include <QtSerialPort>
    
    MasterThread::MasterThread(QObject *parent) : QThread(parent), waitTimeout(0), quit(false)
    {
    
    }
    MasterThread::~MasterThread()
    {
        mutex.lock();
        quit = true;
        cond.wakeOne();
        mutex.unlock();
        wait();
    }
    void MasterThread::transaction(const QString &portName, int waitTimeout, const QByteArray &request)
    {
        //! [1]
        QMutexLocker locker(&mutex);       //it lock the new thread in to the mutex locker while any other thread running
        this->portName = portName;
        this->waitTimeout = waitTimeout;
        this->request = request;
        //! [3]
        if (!isRunning())
            start();
        else
            cond.wakeOne();
    }
    void MasterThread::run()
    {
        bool currentPortNameChanged = false;
    
        mutex.lock();
        //! [4] //! [5]
        if (currentPortName != portName) {
            currentPortName = portName;
            currentPortNameChanged = true;
        }
    
        int currentWaitTimeout = waitTimeout;
        QByteArray currentRequest = request;        //QString currentRequest = request;
        mutex.unlock();
        //! [5] //! [6]
        QSerialPort serial;
    
        while (!quit) {
            //![6] //! [7]
            if (currentPortNameChanged) {
                serial.close();
                serial.setPortName(currentPortName);
                serial.setBaudRate(QSerialPort::Baud9600);                  //baud rate
                serial.setDataBits(QSerialPort::Data8);                     //Data bit
                serial.setParity(QSerialPort::NoParity);                    //no parity
                serial.setStopBits(QSerialPort::OneStop);                   //one stop bit
                serial.setFlowControl(QSerialPort::NoFlowControl);
                if (!serial.open(QIODevice::ReadWrite)) {
                    emit error(tr("Can't open %1, error code %2")
                               .arg(portName).arg(serial.error()));
                    currentPortName.clear();
                    return;
                }
            }
            //! [7] //! [8]
            // write request
    //        QByteArray requestData = currentRequest.toLocal8Bit();
            serial.write(currentRequest);
            if (serial.waitForBytesWritten(waitTimeout)) {
                //! [8] //! [10]
                // read response
                if (serial.waitForReadyRead(currentWaitTimeout)) {
                    QByteArray responseData = serial.readAll();
                    while (serial.waitForReadyRead(20))
                        responseData += serial.readAll();
    
    //                QString response(responseData);
    
                   QString response = QString::fromLocal8Bit(responseData,responseData.size());
                    //! [12]
                    emit this->response(response);
                    //! [10] //! [11] //! [12]
                } else {
                    emit timeout(tr("Wait read response timeout %1")
                                 .arg(QTime::currentTime().toString()));
                }
                //! [9] //! [11]
            } else {
                emit timeout(tr("Wait write request timeout %1")
                             .arg(QTime::currentTime().toString()));
            }
            //! [9]  //! [13]
            mutex.lock();
            cond.wait(&mutex);     //release the locked mutex
            if (currentPortName != portName) {
                currentPortName = portName;
                currentPortNameChanged = true;
            } else {
                currentPortNameChanged = false;
            }
            currentWaitTimeout = waitTimeout;
            currentRequest = request;
            mutex.unlock();
        }
        //! [13]
    }
    
    

    thread 1 calling from the mainwindow class

    thread.transaction(m_settingsDialog->settings().comport,
                           50,
                           datatowrite);
    

    thread2 Method calling from a Dialog class,

    thread2.transaction(COMp```
    code_text
    ```ortRcvd,
                           50,
                           data);
    

    I am new to qt please help me to solve the issue

    Regards,
    Alphy


  • Qt Champions 2019

    @Alphy said in same serial in multiple threads giving error:

    But in my actual application I need to use Same serial terminal in different threads

    Why?!
    If you read documentation (https://doc.qt.io/qt-5/qserialport.html) you will find this:
    "Note: The serial port is always opened with exclusive access (that is, no other process or thread can access an already opened serial port)."



  • I am not sure it is wise to communicate to the same serial from multiple threads, but you could use a signal to do this with the port open in 1 thread. Have the other threads send data via the signal in the 1 thread.



  • Hi,

    I have used signal slot mechanism and it is working fine.

    Thankyou



  • @Alphy said in same serial in multiple threads giving error:

    it is working fine.

    So please don't forget to mark your post as solved!