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 14 May 2020, 10:16 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

    J 1 Reply Last reply 14 May 2020, 10:36
    0
    • A Alphy
      14 May 2020, 10:16

      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

      J Offline
      J Offline
      jsulm
      Lifetime Qt Champion
      wrote on 14 May 2020, 10:36 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 14 May 2020, 14:47 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 15 May 2020, 12:52 last edited by
          #4

          Hi,

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

          Thankyou

          Pablo J. RoginaP 1 Reply Last reply 15 May 2020, 13:52
          0
          • A Alphy
            15 May 2020, 12:52

            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 15 May 2020, 13:52 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

            1/5

            14 May 2020, 10:16

            • Login

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