Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. Mobile and Embedded
  4. Thread that read from QSerialPort

Thread that read from QSerialPort

Scheduled Pinned Locked Moved Mobile and Embedded
21 Posts 4 Posters 12.9k 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.
  • R Offline
    R Offline
    rileo8
    wrote on last edited by
    #1

    Hi,

    i'm developing an application that use QSerialPort.
    I made two threads , one to read and one to write on the serial port.
    I would like to know if i'm doing right..
    this is the implementation of the Rx thread:

    • in the run() function i only inserted a

    @while(!end)
    {
    sleep(1)
    }
    @

    while in the thread declaration i inserted:

    @connect(serialPort, SIGNAL(readyRead()), this, SLOT(ReadFromSerialPort()));@

    So that when there is something on the serial port it calls the ReadFromSerialPort functions.

    Is that the correct way to do? Or i need to remove the signal/slot and insert something in the while(!end) loop to check if there is something to read?

    Thanks,
    Riccardo

    1 Reply Last reply
    0
    • T Offline
      T Offline
      t3685
      wrote on last edited by
      #2

      That is probably not the most efficient way of doing this. QSerialPort can be used either synchronously or asynchronously.

      Synchronously: use waitForReadyRead or waitForBytesWritten, but this will block your thread until either data is received or written. This is bad if you use it in the GUI thread (i.e. the main Qt thread): your application will not respond to user input until the read or write is done.

      Asynchronously: uses signal and slots. In this case you connect to the readyRead signal with your slot (ReadFromSerialPort), and each time data is available the signal will be emitted and your slot will be executed. Now you don't need to wait in a wasteful while loop for data reads or writes + no need for extra threads.
      For more information how this is done internally check:
      https://qt-project.org/wiki/Threads_Events_QObjects#285a62c361be4793a6c10d04e3823a80

      I highly recommend using the second approach, especially if you plan to use more Qt.

      1 Reply Last reply
      0
      • JKSHJ Offline
        JKSHJ Offline
        JKSH
        Moderators
        wrote on last edited by
        #3

        Hi,

        [quote author="rileo8" date="1383151640"]
        @while(!end)
        {
        sleep(1)
        }
        @
        [/quote]This is an infinite loop. It blocks the event loop, which means your thread can't receive any signals.

        How fast is your read/write rate? You might not even need separate threads. See this "official example":http://qt-project.org/doc/qt-5.1/qtserialport/terminal.html -- the QSerialPort lives in the main thread itself.

        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

        1 Reply Last reply
        0
        • R Offline
          R Offline
          rileo8
          wrote on last edited by
          #4

          Hi,

          the problem is that i'm developing an application that communicate with an external interface with the serial port so it continuosly communicate with it while the GUI need to be responsive and accept user input/show values etc...

          So i want to separate read/write from serial port AND the GUI

          What you suggest to do?

          1 Reply Last reply
          0
          • R Offline
            R Offline
            rileo8
            wrote on last edited by
            #5

            Reading the documentation i found that maybe i have to substitute

            @while(!end)
            {
            sleep(1)
            }@

            whit @exec()@

            that enters the event loop and waits until exit() is calle

            Is it correct?

            Thanks

            1 Reply Last reply
            0
            • T Offline
              T Offline
              t3685
              wrote on last edited by
              #6

              No it is not correct. You don't need a wait loop like that.

              1 Reply Last reply
              0
              • JKSHJ Offline
                JKSHJ Offline
                JKSH
                Moderators
                wrote on last edited by
                #7

                [quote author="rileo8" date="1383208867"]that enters the event loop and waits until exit() is calle

                Is it correct?[/quote]Yes, it's correct :)

                Next, read the "Thread Affinity" section of the "QObject documentation":http://doc-snapshot.qt-project.org/qt5-stable/qobject.html#thread-affinity -- it explains how to choose the thread to run your slots.

                [quote author="t3685" date="1383215445"]No it is not correct. You don't need a wait loop like that.[/quote]rileo8 realized that after reading the documentation. That's why he asked if it's correct to replace the wait loop with exec().

                Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                1 Reply Last reply
                0
                • R Offline
                  R Offline
                  rileo8
                  wrote on last edited by
                  #8

                  Ok,

                  i'm understanding that i hadn;t understand qthreads before... :-)
                  The question is :

                  i need a "worker" thread that read and write from a serial port so i can use this approach:

                  class Worker : public QObject
                  {
                  Q_OBJECT
                  private slots:
                  void onTimeout()
                  {
                  qDebug()<<"Worker::onTimeout get called from?: "<<QThread::currentThreadId();
                  }
                  };

                  @class Thread : public QThread
                  {
                  Q_OBJECT

                  private:
                  void run()
                  {
                  qDebug()<<"From work thread: "<<currentThreadId();
                  QTimer timer;
                  Worker worker;
                  connect(&timer, SIGNAL(timeout()), &worker, SLOT(onTimeout()));
                  timer.start(1000);

                      exec&#40;&#41;;
                  }
                  

                  };@

                  the problem is...if i need that the worker thread receive signals from the GUI what i have to do? Connect with signal&slot the GUI withe theThread class and then connect always with signals/slot the thread calls with the worker class?

                  1 Reply Last reply
                  0
                  • JKSHJ Offline
                    JKSHJ Offline
                    JKSH
                    Moderators
                    wrote on last edited by
                    #9

                    To make things simple, you don't need to subclass QThread. Just have the timer in your worker:

                    @
                    class Worker : public QObject
                    {
                    Q_OBJECT
                    QTimer* timer;

                    public:
                    Worker(QObject *parent = 0) : QObject(parent) {
                    // Worker must be parent of QTimer
                    timer = new QTimer(this);
                    connect(timer, SIGNAL(timeout()), this, SLOT(onTimeout()));
                    }

                    public slots:
                    void startWorking() { timer->start(1000); }

                    private slots:
                    void onTimeout() {...}
                    };
                    @

                    @
                    int main(int argc, char *argv[]) {
                    QApplication a(argc, argv);
                    QThread thread;
                    Worker worker;

                    QObject::connect(&thread, SIGNAL(started()),
                            &worker, SLOT(startWorking()));
                    
                    worker.moveToThread(&thread);
                    thread.start();
                    
                    int returnValue = a.exec&#40;&#41;;
                    thread.wait(&#41;;
                    return returnValue;
                    

                    }
                    @

                    You can connect signals and slots directly between your worker and your GUI.

                    Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                    1 Reply Last reply
                    0
                    • R Offline
                      R Offline
                      rileo8
                      wrote on last edited by
                      #10

                      Ok perfect,thanks to everybody for the help!
                      Now i better understand Qthreads...

                      1 Reply Last reply
                      0
                      • JKSHJ Offline
                        JKSHJ Offline
                        JKSH
                        Moderators
                        wrote on last edited by
                        #11

                        You're welcome.

                        Good luck with your project!

                        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                        1 Reply Last reply
                        0
                        • R Offline
                          R Offline
                          rileo8
                          wrote on last edited by
                          #12

                          Hi, i'm stille here with another question..

                          now my code loooks like this:

                          @#include "mainwindow.h"
                          #include <QtGui/QApplication>
                          #include <QThread>

                          #include "executer.h"
                          #include "checker.h"
                          #include "networker.h"

                          int main(int argc, char *argv[])
                          {
                          QApplication a(argc, argv);
                          MainWindow w;
                          w.showMaximized();

                          Checker checker;
                          Networker networker;
                          Executer executer;

                          QThread checkerThread;
                          QThread networkerThread;
                          QThread executerThread;

                          QObject::connect(&executerThread,SIGNAL(started()),&executer,SLOT(Start()));

                          checker.moveToThread(&checkerThread);
                          networker.moveToThread(&networkerThread);
                          executer.moveToThread(&executerThread);

                          checkerThread.start();
                          networkerThread.start();
                          executerThread.start();

                          int returnValue=a.exec();

                          executerThread.wait();

                          return returnValue;

                          }
                          @

                          i neew to share an object (of a custom Configuration type) between all trheads.

                          Is it coorect to declare it in the main, pass it to all htreads and also share a mutex so that every thread lock and unlock it?

                          Thanks

                          1 Reply Last reply
                          0
                          • JKSHJ Offline
                            JKSHJ Offline
                            JKSH
                            Moderators
                            wrote on last edited by
                            #13

                            If it is not a QObject, then yes you can do that.

                            If it is a QObject, then you are not allowed to share it between threads. QObject is not thread-safe.

                            See this page for info on how to share data between threads: http://doc-snapshot.qt-project.org/qt5-stable/threads-synchronizing.html

                            Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                            1 Reply Last reply
                            0
                            • T Offline
                              T Offline
                              t3685
                              wrote on last edited by
                              #14

                              [quote author="JKSH" date="1383215991"][quote author="rileo8" date="1383208867"]that enters the event loop and waits until exit() is calle

                              Is it correct?[/quote]Yes, it's correct :)

                              Next, read the "Thread Affinity" section of the "QObject documentation":http://doc-snapshot.qt-project.org/qt5-stable/qobject.html#thread-affinity -- it explains how to choose the thread to run your slots.

                              [quote author="t3685" date="1383215445"]No it is not correct. You don't need a wait loop like that.[/quote]rileo8 realized that after reading the documentation. That's why he asked if it's correct to replace the wait loop with exec().[/quote]

                              The QSerialPort class is asynchronous. You don't need threads to do this.

                              1 Reply Last reply
                              0
                              • R Offline
                                R Offline
                                rileo8
                                wrote on last edited by
                                #15

                                It is not a QObject, is a simple c++ custom class

                                1 Reply Last reply
                                0
                                • JKSHJ Offline
                                  JKSHJ Offline
                                  JKSH
                                  Moderators
                                  wrote on last edited by
                                  #16

                                  [quote author="t3685" date="1383225223"]The QSerialPort class is asynchronous. You don't need threads to do this.[/quote]Yes, if I/O is slow enough, then no threads are needed. That's why I asked about the read/write rate.

                                  Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                                  1 Reply Last reply
                                  0
                                  • R Offline
                                    R Offline
                                    rileo8
                                    wrote on last edited by
                                    #17

                                    Yes i understood this,
                                    infact now i have:

                                    GUI thread
                                    thread for operations on serialport 1
                                    thread for operations on serialport 2
                                    thread for network operations

                                    Now i also added a custom Configuration class that is share d between threads with a shared QMutex to enable access to it

                                    1 Reply Last reply
                                    0
                                    • T Offline
                                      T Offline
                                      t3685
                                      wrote on last edited by
                                      #18

                                      [quote author="JKSH" date="1383225543"][quote author="t3685" date="1383225223"]The QSerialPort class is asynchronous. You don't need threads to do this.[/quote]Yes, if I/O is slow enough, then no threads are needed. That's why I asked about the read/write rate.[/quote]

                                      The write function returns immediately. The readyRead() signal is only emitted when data is available. I don't think it matters then what the Baud rate is.

                                      http://qt-project.org/doc/qt-5.1/qtserialport/terminal.html

                                      1 Reply Last reply
                                      0
                                      • JKSHJ Offline
                                        JKSHJ Offline
                                        JKSH
                                        Moderators
                                        wrote on last edited by
                                        #19

                                        [quote author="t3685" date="1383225815"]
                                        The write function returns immediately. The readyRead() signal is only emitted when data is available. I don't think it matters then what the Baud rate is.[/quote]Sorry for being unclear; I meant the rate at which read() and write() need to be called (relative to other operations). An active thread will experience jitter, especially on a non-real-time OS. That raises the possibility of a buffer becoming empty. Depending on how the devices have been designed, an empty write buffer could kill the entire connection.

                                        t3685 has a very valid point though. rileo8, try running your workers in the main thread first using the asynchronous API, and see how your program performs. You might not need 3 extra threads.

                                        Qt Doc Search for browsers: forum.qt.io/topic/35616/web-browser-extension-for-improved-doc-searches

                                        1 Reply Last reply
                                        0
                                        • R Offline
                                          R Offline
                                          rileo8
                                          wrote on last edited by
                                          #20

                                          Hi,

                                          my point is that i need to accomplish different operations on 2 serial ports and also network operations so i think that putting all i t he gui can cause gui freezing...

                                          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