Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Behind the Scenes
  3. Wiki Discussion
  4. same serial in multiple threads giving error
QtWS25 Last Chance

same serial in multiple threads giving error

Scheduled Pinned Locked Moved Solved Wiki Discussion
multithreadingserial port
5 Posts 4 Posters 2.6k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • A Offline
    A Offline
    Alphy
    wrote on last edited by
    #1

    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

    jsulmJ 1 Reply Last reply
    0
    • A Alphy

      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

      jsulmJ Offline
      jsulmJ Offline
      jsulm
      Lifetime Qt Champion
      wrote on last edited by
      #2

      @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)."

      https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      4
      • fcarneyF Offline
        fcarneyF Offline
        fcarney
        wrote on last edited by
        #3

        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.

        C++ is a perfectly valid school of magic.

        1 Reply Last reply
        2
        • A Offline
          A Offline
          Alphy
          wrote on last edited by
          #4

          Hi,

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

          Thankyou

          Pablo J. RoginaP 1 Reply Last reply
          0
          • A Alphy

            Hi,

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

            Thankyou

            Pablo J. RoginaP Offline
            Pablo J. RoginaP Offline
            Pablo J. Rogina
            wrote on last edited by
            #5

            @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!

            Upvote the answer(s) that helped you solve the issue
            Use "Topic Tools" button to mark your post as Solved
            Add screenshots via postimage.org
            Don't ask support requests via chat/PM. Please use the forum so others can benefit from the solution in the future

            1 Reply Last reply
            0

            • Login

            • Login or register to search.
            • First post
              Last post
            0
            • Categories
            • Recent
            • Tags
            • Popular
            • Users
            • Groups
            • Search
            • Get Qt Extensions
            • Unsolved