[SOLVED] Split Terminal example into Two threads



  • Hi,

    I am a newbie of Qt, working on multi-sensors control through Qt Creator.
    My aim is to control multi-sensors, retrieve data through multi Serial (COM) Ports.

    I tried to modify the "Terminal" Qt example, split it and put the "MainWindow" class in a new thread instead of main thread; however only QMainWindow, which is derived from QWidget instead of QObject, cannot be put in a new thread.

    If I want to retrieve data from two sensor through two COM serial ports simultaneously, it has to be working on two different threads.

    Could anyone tell me, how can I modify the "Terminal" example to put the serial communication into an extra thread?

    Thank you very much!



  • This post is deleted!


  • I don't think you need threads in this case. QSerialPort is non-blocking by design. Connecting to the readReady() signal should be enough. Just duplicate the code you have for the serial port in the example.



  • I haven't worked with the QSerialPort before, but the document say that this class support asynchronous operations, so you may not need to open a new thread to communicate with two com ports, just create another QSerialPort and use the asynchronous api to get and set your data, this way you do not need to bother lock issue(or you prefer atomic data?), how to pass the data between main thread and worker thread etc.

    Usually, I avoid to use multithread if single thread works fine for me(unless I am doing some experiment :) )

    If you really need to use multithread, you could study the document of Qt5, it show us how to use QThread quite clear.



  • @Leonardo
    Actually one of the reasons I want it to be multi-threads is, the working speed to retrieve data would not reduce by half.
    The priority is to let them work as fast as possible.



  • @stereomatchingkiss
    The priority is to let multi-sensors work simultaneously on the fastest speed to get data back; that is why I want it to be multi-threads.

    I read a lot documents of Qt threading, and am working on "splitting" the "MainWindow" apart from QMainWindow (QWidget), and try to put it in QObject so that it could be in a new thread.

    However, as a newbie of Qt, that is not easy; or I do not even know is that possible or not.



  • You're underestimating your application. I think your code is able to process the received data faster than the serial port can transmit new data.

    If you're still interested in threads, you don't need to split the mainwindow. Keep the main gui where it is and move the serial port handling logic to a separate thread. Then you should emit signals that the main window will catch whenever a gui update is required.



  • @Leonardo
    Yes, you are right.
    The bottleneck could be serial port transmit, that is why I want the serial port communication to be in a new thread, how many sensors means how many COMs.

    The serial port handling logic was written in "MainWindow", and my aim is to split that part to put it in a new thread.

    We got the same idea.



  • If you agree that the serial port is the bottleneck, then you don't need threads. It seems like you think that QSerialPort would not handle both ports properly, but that's not the case. As I said before, QSerialPort is non-blocking by design. It implies that somehow threads are already used in its internals. Your application will not block while reading data, only when processing it in the readReady() signal, which should be very fast.



  • @Leonardo
    Seems great!
    I will try it and talk about it with you later.

    Thank you!



  • @Leonardo
    Hi,

    It comes out that, the slot in SerialPort related Object never works;

    myDefaulSerialObject = new SenSerialControlAlgorithmObject();
    mySerialThread = new QThread();
    myDefaulSerialObject->moveToThread(mySerialThread); // It works well if I Comment Select this line and without Qt::QueuedConnection
    

    even if without moving the Object into a new thread, just added Qt::QueuedConnection after SIGNAl/SLOT, the slot doesn't work, either.

    connect(this, SIGNAL(emitOpenSerialOrder(SenSettingsDialog::Settings)), myDefaulSerialObject, SLOT(openSerialPort(SenSettingsDialog::Settings)), Qt::QueuedConnection);
    

    Is that only because of its non-blocking attribute, so that I cannot even use Qt::QueuedConnection in main thread?

    Thank you!



  • Hi. I thought you were going to use the QSerialPort class. I don't know this class you're using.



  • When using QSerialPort the bottleneck often exists in the plotting or showing of the data.
    The ui widgets are to slow to keep up with a 100% loaded 9600 8n1 bus. This also applies to VC++ and C#.

    To get asynchronous and more flexible you could move your serialport to a different thread/process and then converting it to a TCP socket. Localhost sockets are fast, and buffered.

    Bonus:

    1. you are able to read sensors over the network.
    2. if the port crashes, the gui (with the data) doesn't.
    3. your gui is truly platform independent.
      I did something similar. But instead of using two ports, I merged data over 1 port, called MultiTerminal.


  • @Jeroen3
    Thank you for your sharing!