Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. QSerialPort doesn't work in QThread
Forum Updated to NodeBB v4.3 + New Features

QSerialPort doesn't work in QThread

Scheduled Pinned Locked Moved Solved General and Desktop
18 Posts 6 Posters 4.1k 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.
  • AlienA Alien

    Guys thank you for replying me,
    I searched around this problem before posting the question I know that run function will execute in another thread that's why I put init function inside the run function @aha_1980 is it wrong to put init function in run or is it wrong to have it private ?
    @J-Hilk "Overwriting run is for your use case inadequate/not recommended." what is recommended?
    I can't get your point could you please give me more information? (Also I change PORT_NAME and BAUD_RATE still the application doesnt' work)
    @JonB does it work for you? could you please put the code here ?

    J.HilkJ Offline
    J.HilkJ Offline
    J.Hilk
    Moderators
    wrote on last edited by
    #9

    @Alien

    I would imagen, that your QSerialPort will not only send data once, but your goal is a communication between your app and your hardware.

    Howver by overwriting Run, you will end up implementing your very own SIGNAL/SLOT handling, data passing between threads etc.

    By going with Worker-class QThread::moveToThread, you end up passing a lot of work to the framework.

    Also it has the nice benefit of, you can create your QSerialport in its own class non threaded, make sure, everything works as you want it to and move it later into its own Thread without nearly any changes insde of your code.


    Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


    Q: What's that?
    A: It's blue light.
    Q: What does it do?
    A: It turns blue.

    1 Reply Last reply
    3
    • AlienA Offline
      AlienA Offline
      Alien
      wrote on last edited by
      #10

      @J-Hilk I've read how-to-really-truly-use-qthreads-the-full-explanation I can't understand why she wrote
      "
      The main thing to keep in mind when using a QThread is that it’s not a thread. It’s a wrapper around a thread object. This wrapper provides the signals, slots and methods to easily use the thread object within a Qt project. This should immediately show why the recommended way of using QThreads in the documentation, namely to sub-class it and implement your own run() function, is very wrong.
      "
      If overriding run function is very wrong why QT documentation examples introduce this way even in QT 5.11 ? Also I use Maya Posch approach still my app can't use serial port in a thread

      J.HilkJ 1 Reply Last reply
      0
      • VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by VRonin
        #11

        You are probably just deleting the serial port too early. The easy but ugly way to solve would be adding m_serialPort->waitForBytesWritten after m_serialPort->write.

        Your CThread destructor is a race condition. It is executed in the main thread and you are calling methods on m_serialPort and even worse deleting it directly.

        I really recommend you follow @J-Hilk 's advice https://forum.qt.io/topic/91681/qserialport-doesn-t-work-in-qthread/4

        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
        ~Napoleon Bonaparte

        On a crusade to banish setIndexWidget() from the holy land of Qt

        AlienA 1 Reply Last reply
        2
        • VRoninV VRonin

          You are probably just deleting the serial port too early. The easy but ugly way to solve would be adding m_serialPort->waitForBytesWritten after m_serialPort->write.

          Your CThread destructor is a race condition. It is executed in the main thread and you are calling methods on m_serialPort and even worse deleting it directly.

          I really recommend you follow @J-Hilk 's advice https://forum.qt.io/topic/91681/qserialport-doesn-t-work-in-qthread/4

          AlienA Offline
          AlienA Offline
          Alien
          wrote on last edited by Alien
          #12

          @VRonin said in QSerialPort doesn't work in QThread:

          m_serialPort->waitForBytesWritten

          what do you recommend me to use qserial in qthread?

          1 Reply Last reply
          0
          • AlienA Alien

            @J-Hilk I've read how-to-really-truly-use-qthreads-the-full-explanation I can't understand why she wrote
            "
            The main thing to keep in mind when using a QThread is that it’s not a thread. It’s a wrapper around a thread object. This wrapper provides the signals, slots and methods to easily use the thread object within a Qt project. This should immediately show why the recommended way of using QThreads in the documentation, namely to sub-class it and implement your own run() function, is very wrong.
            "
            If overriding run function is very wrong why QT documentation examples introduce this way even in QT 5.11 ? Also I use Maya Posch approach still my app can't use serial port in a thread

            J.HilkJ Offline
            J.HilkJ Offline
            J.Hilk
            Moderators
            wrote on last edited by
            #13

            @Alien said in QSerialPort doesn't work in QThread:

            If overriding run function is very wrong why QT documentation examples introduce this way even in QT 5.11 ? Also I use Maya Posch approach still my app can't use serial port in a thread

            it doesn't,
            Check the details from the QThread docu:
            http://doc.qt.io/qt-5/qthread.html#details

            cleary a worker approach, to overwrite QThread is the 2nd example, and in my opinion should be removed. But thats far from my call and probably still there for legacy reasons.

            This was change to the docs was made with Qt5.9 iirc.


            Be aware of the Qt Code of Conduct, when posting : https://forum.qt.io/topic/113070/qt-code-of-conduct


            Q: What's that?
            A: It's blue light.
            Q: What does it do?
            A: It turns blue.

            1 Reply Last reply
            0
            • BuckwheatB Offline
              BuckwheatB Offline
              Buckwheat
              wrote on last edited by
              #14

              Hello and welcome @Alien ,

              I am glad your read May's blog and redid your threading. The worker thread approach is a best way to setup the threads. With your serial port in the worker object you will only need QThread to run the event queue which is VERY important to QSerialPort event handling. As you have already found out, overriding "run" will block event queue processing.

              One thing I did not see is where you are connecting to the readyRead signal. This will allow your worker object to read the data from the serialport as it arrives.

              If you are still having issues, post your new threading model so we can see where the disconnect is happening and our eyes can give you insight.

              Dave Fileccia

              AlienA 1 Reply Last reply
              1
              • AlienA Offline
                AlienA Offline
                Alien
                wrote on last edited by Alien
                #15

                Thanks for all of your help

                If my undrestanding is right its a bad idea to use aserialport inside a thread while qserialport is async itself also when I implement qthread's run function actually I disrupt the event dispatcher of that thread so signal and slot can't work properly for qserialport in thread due to the infinite while inside the run.

                If my undrestanig is still wrong please help me and make me aware of that
                Yours,

                1 Reply Last reply
                0
                • BuckwheatB Buckwheat

                  Hello and welcome @Alien ,

                  I am glad your read May's blog and redid your threading. The worker thread approach is a best way to setup the threads. With your serial port in the worker object you will only need QThread to run the event queue which is VERY important to QSerialPort event handling. As you have already found out, overriding "run" will block event queue processing.

                  One thing I did not see is where you are connecting to the readyRead signal. This will allow your worker object to read the data from the serialport as it arrives.

                  If you are still having issues, post your new threading model so we can see where the disconnect is happening and our eyes can give you insight.

                  AlienA Offline
                  AlienA Offline
                  Alien
                  wrote on last edited by
                  #16

                  @Buckwheat how to run event queue inside my thread?
                  A snippet code would be helpfull

                  1 Reply Last reply
                  0
                  • VRoninV Offline
                    VRoninV Offline
                    VRonin
                    wrote on last edited by
                    #17

                    call QThread::exec() inside run().
                    I still suggest you convert to the worker object design though

                    "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                    ~Napoleon Bonaparte

                    On a crusade to banish setIndexWidget() from the holy land of Qt

                    1 Reply Last reply
                    3
                    • BuckwheatB Offline
                      BuckwheatB Offline
                      Buckwheat
                      wrote on last edited by VRonin
                      #18

                      @Alien,

                      QThread has an event queue and will run freely if you do NOT override run! Using the technique outlined by May will allow the thread's event queue to run. You just need to connect your signals for the serial port and things will run freely. Here is a sample for starting a GNSS receiver in a thread (using May's method):

                      *** NOTE: This is really pseudo code as it comes from our proprietary code ***

                         mpQ_GnssRcvrThread = new QThread;
                      
                         // The receiver code is implemented in an event-based fashion as a QObject
                         // but will be owned by a dedicated thread, to ensure independence from
                         // risk of blocking operations being used by other parts of the system.
                         mpQ_GnssRcvr->moveToThread (mpQ_GnssRcvrThread);
                      
                         // Trigger worker start upon thread start
                         connect (mpQ_GnssRcvrThread, &QThread::started, mpQ_GnssRcvr, &GNSSReceiver::start);
                      
                         // Delete
                         connect (mpQ_GnssRcvrThread, &QThread::finished, mpQ_GnssRcvr, &GNSSReceiver::deleteLater);
                         connect (mpQ_GnssRcvrThread, &QThread::finished, mpQ_GnssRcvrThread, QThread::deleteLater);
                      
                      Now in the GNSSReceiver object (derived from QObject):
                         mQ_SerialPort= new QSerialPort (this);
                         mQ_SerialPort->open (...);
                      
                         // Connect data handling
                         connect (mQ_SerialPort, &QSerialPort::readyRead, this, &handleCommsChan);
                      
                      In handleCommsChan:
                      
                      QByteArray Q_Data = mQ_SerialPort->readAll ();
                      
                      ...
                      do stuff
                      ...
                      
                      

                      The GNSSReceiver object runs inside of the QThread event loop. Writing to the serial port can be done asynchronously. The only Qt object that has issues with worker objects is QTimer. They need to be created in the thread space and assert errors if you try to start/stop them outside of the thread.

                      I use this technique for serial port, network, and serial bus (CAN) interfacing (asynchronous objects). I am liking QFuture for worker threads (functions to do something) currently.

                      @VRonin, as you know, if you get rid of run (or at least use run to initialize your thread and call QThread::exec on exiting) the thread works. I prefer to treat the thread as a container and just call object->moveToThread (new QThread) myself for most things.

                      Dave Fileccia

                      1 Reply Last reply
                      1

                      • Login

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