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. Worker threads with shared resources in Qt application
QtWS25 Last Chance

Worker threads with shared resources in Qt application

Scheduled Pinned Locked Moved Solved General and Desktop
qt5.8qserialportqthreadworkerthread
8 Posts 4 Posters 4.0k 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.
  • M Offline
    M Offline
    mkaze
    wrote on last edited by
    #1

    I am working on a Qt application which involves serial communication with one or multiple devices. There are different procedures that can be executed simulteanously and each procedure may send one or unknown number of commands to a device and may receive data in response. To make it more clear, here is a graphical illustration of the scenario:
    enter image description here

    Clicking on a button triggers the execution of the corresponding procedure. So two or more different procedures may be running at the same time when the user clicks on two or more buttons in a short interval. Actually the only thing that may be shared between them is the serial communication with a single device; otherwise they are mostly independent of one another. And here are two pseudo-code examples of what a procedure may look like:

    Procedure A:

    begin
    write command a1 on serial port
    wait for one second
    perform some computations
    write command a2 on serial port
    wait for one second
    end
    

    Procedure B:

    begin
    while true:
        write command b1 on serial port
        read the response from serial port
        perform some computations
        if a condition holds return, otherwise continue
    end
    

    My solution and its issue:

    To simplify the situation consider that there is only one device which we need to communicate with. Since procedures can be executed simulteanously (and only one of them can communicate with the device through serial port at a time) I have created one thread and one worker class for each of the procedures and have moved the workers to their corresponding threads. To synchronize procedures when accessing the serial port I have created one mutex:

    MainWindow.h

    class MainWindow : public QMainWindow {
    
    public:
        //...
        QSerialPort*	serial_;
        QMutex		serial_mutex_;
    
    private:
        //...
        ProcAWorker*	proca_worker;
        ProcBWorker*	procb_worker;
        ProcCWorker*	procc_worker;
        ProcDWorker*	procd_worker;
    
        QThread		proca_thread;
        QThread		procb_thread;
        QThread		procc_thread;
        QThread		procd_thread;
    
    }
    

    MainWindow.cpp

    void MainWindow::onConnectButtonClicked()
    {
        serial_ = new QSerialPort();
        // configure serial port settings
        
        serial_->open(QIODevice::ReadWrite);
    }
    
    void MainWindow::onButtonAClicked()
    {
        proca_worker = new ProcAWorker(0, this);   // pass a pointer to this class to be able to access its methods and members
        proca_worker->moveToThread(&proca_thread);
        
        // setup worker-thread connections: started, quit, finished, etc.
    
        proca_thread.start();    // triggers `proccess` slot in proca_worker
    }
    
    // same thing for other buttons and procedures
    

    ProcAWorker.cpp

    void ProcAWorker::ProcAWorker(QObject *parent, QMainWindow *wnd) :
    	QObject(parent), wnd_(wnd)
    {
    
    }
    
    void ProcAWorker::process()
    {
        wnd_->serial_mutex_->lock();
        wnd_->serial_->write('Command a1');   // Warning occurs in this line
        bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
        wnd_->serial_mutex_->unlock();
        
        QThread::sleep(1);
        // perform some computations
        
        wnd_->serial_mutex_->lock();
        wnd_->serial_->write('Command a2');
        bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
        wnd_->serial_mutex_->unlock();
    
        if (write_ok) {
            // signal successful to main window
            emit success();
        }
    }
    

    However, when the write operation is performed on the serial port (i.e. wnd_->serial_->write('Command a1');) the following warning is shown:

    QObject: Cannot create children for a parent that is in a different
    thread. (Parent is QSerialPort(0x18907d0), parent's thread is
    QThread(0x13cbc50), current thread is QThread(0x17d8d08)

    My questions:

    1. I have already looked at questions on Stackoverflow regarding this warning, but their answers have only mentioned that signal/slot should be used. I am familiar with using signal/slot to communicate with worker threads. However, I can't figure out how to implement my specific scenario (simultaneous running procedures with shared resources like serial port) using signal/slot or how can I modify my current solution to resolve this issue? Note that the procedures should be allowed to run in parallel (unless in those moments when they want to communicate with the device). Obviously one can run the procedures sequentially (i.e. one after another) but I am not looking for such solutions.

    2. Actually there is also a "Halt" button that stops all the running procedures and sends a halt command to the device. But I could not figure out to implement this functionality as well (set a flag, send a quit signal, etc.). Could you please give me some hints in this regards as well?

    VRoninV 1 Reply Last reply
    0
    • M mkaze

      I am working on a Qt application which involves serial communication with one or multiple devices. There are different procedures that can be executed simulteanously and each procedure may send one or unknown number of commands to a device and may receive data in response. To make it more clear, here is a graphical illustration of the scenario:
      enter image description here

      Clicking on a button triggers the execution of the corresponding procedure. So two or more different procedures may be running at the same time when the user clicks on two or more buttons in a short interval. Actually the only thing that may be shared between them is the serial communication with a single device; otherwise they are mostly independent of one another. And here are two pseudo-code examples of what a procedure may look like:

      Procedure A:

      begin
      write command a1 on serial port
      wait for one second
      perform some computations
      write command a2 on serial port
      wait for one second
      end
      

      Procedure B:

      begin
      while true:
          write command b1 on serial port
          read the response from serial port
          perform some computations
          if a condition holds return, otherwise continue
      end
      

      My solution and its issue:

      To simplify the situation consider that there is only one device which we need to communicate with. Since procedures can be executed simulteanously (and only one of them can communicate with the device through serial port at a time) I have created one thread and one worker class for each of the procedures and have moved the workers to their corresponding threads. To synchronize procedures when accessing the serial port I have created one mutex:

      MainWindow.h

      class MainWindow : public QMainWindow {
      
      public:
          //...
          QSerialPort*	serial_;
          QMutex		serial_mutex_;
      
      private:
          //...
          ProcAWorker*	proca_worker;
          ProcBWorker*	procb_worker;
          ProcCWorker*	procc_worker;
          ProcDWorker*	procd_worker;
      
          QThread		proca_thread;
          QThread		procb_thread;
          QThread		procc_thread;
          QThread		procd_thread;
      
      }
      

      MainWindow.cpp

      void MainWindow::onConnectButtonClicked()
      {
          serial_ = new QSerialPort();
          // configure serial port settings
          
          serial_->open(QIODevice::ReadWrite);
      }
      
      void MainWindow::onButtonAClicked()
      {
          proca_worker = new ProcAWorker(0, this);   // pass a pointer to this class to be able to access its methods and members
          proca_worker->moveToThread(&proca_thread);
          
          // setup worker-thread connections: started, quit, finished, etc.
      
          proca_thread.start();    // triggers `proccess` slot in proca_worker
      }
      
      // same thing for other buttons and procedures
      

      ProcAWorker.cpp

      void ProcAWorker::ProcAWorker(QObject *parent, QMainWindow *wnd) :
      	QObject(parent), wnd_(wnd)
      {
      
      }
      
      void ProcAWorker::process()
      {
          wnd_->serial_mutex_->lock();
          wnd_->serial_->write('Command a1');   // Warning occurs in this line
          bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
          wnd_->serial_mutex_->unlock();
          
          QThread::sleep(1);
          // perform some computations
          
          wnd_->serial_mutex_->lock();
          wnd_->serial_->write('Command a2');
          bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
          wnd_->serial_mutex_->unlock();
      
          if (write_ok) {
              // signal successful to main window
              emit success();
          }
      }
      

      However, when the write operation is performed on the serial port (i.e. wnd_->serial_->write('Command a1');) the following warning is shown:

      QObject: Cannot create children for a parent that is in a different
      thread. (Parent is QSerialPort(0x18907d0), parent's thread is
      QThread(0x13cbc50), current thread is QThread(0x17d8d08)

      My questions:

      1. I have already looked at questions on Stackoverflow regarding this warning, but their answers have only mentioned that signal/slot should be used. I am familiar with using signal/slot to communicate with worker threads. However, I can't figure out how to implement my specific scenario (simultaneous running procedures with shared resources like serial port) using signal/slot or how can I modify my current solution to resolve this issue? Note that the procedures should be allowed to run in parallel (unless in those moments when they want to communicate with the device). Obviously one can run the procedures sequentially (i.e. one after another) but I am not looking for such solutions.

      2. Actually there is also a "Halt" button that stops all the running procedures and sends a halt command to the device. But I could not figure out to implement this functionality as well (set a flag, send a quit signal, etc.). Could you please give me some hints in this regards as well?

      VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by VRonin
      #2

      @mkaze said in Worker threads with shared resources in Qt application:

      but their answers have only mentioned that signal/slot should be used.

      And they are correct. This is the S of S.O.L.I.D.. the worker shouldn't care about writing to serial, that's not its job, it just have to dump the data to someone else and carry on.
      To give you a rule of thumb if you find yourself doing something like:

      proca_worker = new ProcAWorker(0, this);   // pass a pointer to this class to be able to access its methods and members
      

      your design is wrong.

      in ProcAWorker create a Q_SIGNAL void sendDataToSerial(const QByteArray& data); then in MainWindow add connect(proca_worker ,&ProcAWorker::sendDataToSerial,this,[=](const QByteArray& data){if(serial_) serial_->write(data);}); no need for mutex or wait conditions

      Actually there is also a "Halt" button that stops all the running procedures and sends a halt command to the device.

      for this it really depends on what the worker does. you should have a slot in the worker that stops everything and connect it the halt signal. however, for it to work properly you either need not to block the event loop of the secondary thread or to call QCoreApplication::processEvents() every once in a while.

      P.S.
      in MainWindow::onConnectButtonClicked you are leaking serial_ if that method is executed more than once

      "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

      M 1 Reply Last reply
      6
      • VRoninV VRonin

        @mkaze said in Worker threads with shared resources in Qt application:

        but their answers have only mentioned that signal/slot should be used.

        And they are correct. This is the S of S.O.L.I.D.. the worker shouldn't care about writing to serial, that's not its job, it just have to dump the data to someone else and carry on.
        To give you a rule of thumb if you find yourself doing something like:

        proca_worker = new ProcAWorker(0, this);   // pass a pointer to this class to be able to access its methods and members
        

        your design is wrong.

        in ProcAWorker create a Q_SIGNAL void sendDataToSerial(const QByteArray& data); then in MainWindow add connect(proca_worker ,&ProcAWorker::sendDataToSerial,this,[=](const QByteArray& data){if(serial_) serial_->write(data);}); no need for mutex or wait conditions

        Actually there is also a "Halt" button that stops all the running procedures and sends a halt command to the device.

        for this it really depends on what the worker does. you should have a slot in the worker that stops everything and connect it the halt signal. however, for it to work properly you either need not to block the event loop of the secondary thread or to call QCoreApplication::processEvents() every once in a while.

        P.S.
        in MainWindow::onConnectButtonClicked you are leaking serial_ if that method is executed more than once

        M Offline
        M Offline
        mkaze
        wrote on last edited by mkaze
        #3

        @VRonin Thanks. You are right that by using signal/slots then there is no need to use mutex since the requests of serial write or serial read is queued in the event loop of MainWindow and processed sequentially (i.e. only the request of one procedure is handled at a time and therefore there is no race condition here).
        Actually, this solution came to my mind but I thought it would make implementing the procedures fairly complicated. Consider the code for ProcAWorker :

        void ProcAWorker::process()
        {
            wnd_->serial_mutex_->lock();
            wnd_->serial_->write('Command a1');   // Warning occurs in this line
            bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
            wnd_->serial_mutex_->unlock();
            
            QThread::sleep(1);
            // perform some computations
            
            wnd_->serial_mutex_->lock();
            wnd_->serial_->write('Command a2');
            bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
            wnd_->serial_mutex_->unlock();
        
            if (write_ok) {
                // signal successful to main window
                emit success();
            }
        }
        

        To use signal and slots it seems to me that the following considerations should be taken into account:
        1- This way the workflow of procedure workers would be asynchronous I think. For example considering the code above, first a sendDataToSerial signal is emitted. Then from the corresponding slot in MainWindow the result of writing to serial port should be sent back to the procedure by emitting another signal. So the ProcAWorker would need to store its state i.e. what has been done (the first command has been sent) and what needs to be done (is waiting for the result of first write and also the second command needs to be sent). I think it should be implemented as a state machine, right? If that's the case then implementing complex procedures (like the procedure B I mentioned in my question) would be much more complicated.

        2- We need to send back the result of writing to or reading from serial port to the corresponding procedure. One workaround is to pass additional arguments like a flag (or a pointer) to the signal emitted from procedure workers (e.g. sendDataToSerial). What do you suggest?

        Additionally, If we use the signal/slot solution then I think it is better to create a serial worker and move that to a new thread as well, in order to keep the GUI (i.e. MainWindow) responsive.

        Also thanks for mentioning the leakage of serial_ .

        P.S.
        You mentioned that passing a class pointer to a class that contains that class is a wrong design. So I was wondering why is it done in Qt, i.e. when the QObject class (and its inherited classes from it) get a parent pointer argument? (actually the first argument of constructor of ProcAWorker is exactly this). How is it different?

        jsulmJ VRoninV 2 Replies Last reply
        0
        • M mkaze

          @VRonin Thanks. You are right that by using signal/slots then there is no need to use mutex since the requests of serial write or serial read is queued in the event loop of MainWindow and processed sequentially (i.e. only the request of one procedure is handled at a time and therefore there is no race condition here).
          Actually, this solution came to my mind but I thought it would make implementing the procedures fairly complicated. Consider the code for ProcAWorker :

          void ProcAWorker::process()
          {
              wnd_->serial_mutex_->lock();
              wnd_->serial_->write('Command a1');   // Warning occurs in this line
              bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
              wnd_->serial_mutex_->unlock();
              
              QThread::sleep(1);
              // perform some computations
              
              wnd_->serial_mutex_->lock();
              wnd_->serial_->write('Command a2');
              bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
              wnd_->serial_mutex_->unlock();
          
              if (write_ok) {
                  // signal successful to main window
                  emit success();
              }
          }
          

          To use signal and slots it seems to me that the following considerations should be taken into account:
          1- This way the workflow of procedure workers would be asynchronous I think. For example considering the code above, first a sendDataToSerial signal is emitted. Then from the corresponding slot in MainWindow the result of writing to serial port should be sent back to the procedure by emitting another signal. So the ProcAWorker would need to store its state i.e. what has been done (the first command has been sent) and what needs to be done (is waiting for the result of first write and also the second command needs to be sent). I think it should be implemented as a state machine, right? If that's the case then implementing complex procedures (like the procedure B I mentioned in my question) would be much more complicated.

          2- We need to send back the result of writing to or reading from serial port to the corresponding procedure. One workaround is to pass additional arguments like a flag (or a pointer) to the signal emitted from procedure workers (e.g. sendDataToSerial). What do you suggest?

          Additionally, If we use the signal/slot solution then I think it is better to create a serial worker and move that to a new thread as well, in order to keep the GUI (i.e. MainWindow) responsive.

          Also thanks for mentioning the leakage of serial_ .

          P.S.
          You mentioned that passing a class pointer to a class that contains that class is a wrong design. So I was wondering why is it done in Qt, i.e. when the QObject class (and its inherited classes from it) get a parent pointer argument? (actually the first argument of constructor of ProcAWorker is exactly this). How is it different?

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

          @mkaze said in Worker threads with shared resources in Qt application:

          You mentioned that passing a class pointer to a class that contains that class is a wrong design

          Because a worker thread should not call anything from "this" directly what ever this is. Use signals/slots. The purpose of passing this in Qt is completely other topic (parent/child).

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

          1 Reply Last reply
          2
          • mrdebugM Offline
            mrdebugM Offline
            mrdebug
            wrote on last edited by
            #5

            Hi. I suggest you this type of architecture:

            • Create the QSerialPort object inside the run() methot on the only thread that is managing the serial port. The QSerialPort object must be private.
            • To send commands at the devices please implement a ProcessCommand(int CommandType, int Arg0 ...) function.
            • To have back data please use signal and slots.

            So for example, from the main gui
            object->ProcessCommand(FIRMWARE_GET);
            The ProcessCommand function, using mutex, will put in the queue the commands to send by the thread

            Need programmers to hire?
            www.labcsp.com
            www.denisgottardello.it
            GMT+1
            Skype: mrdebug

            1 Reply Last reply
            0
            • M mkaze

              @VRonin Thanks. You are right that by using signal/slots then there is no need to use mutex since the requests of serial write or serial read is queued in the event loop of MainWindow and processed sequentially (i.e. only the request of one procedure is handled at a time and therefore there is no race condition here).
              Actually, this solution came to my mind but I thought it would make implementing the procedures fairly complicated. Consider the code for ProcAWorker :

              void ProcAWorker::process()
              {
                  wnd_->serial_mutex_->lock();
                  wnd_->serial_->write('Command a1');   // Warning occurs in this line
                  bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
                  wnd_->serial_mutex_->unlock();
                  
                  QThread::sleep(1);
                  // perform some computations
                  
                  wnd_->serial_mutex_->lock();
                  wnd_->serial_->write('Command a2');
                  bool write_ok = client_->serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
                  wnd_->serial_mutex_->unlock();
              
                  if (write_ok) {
                      // signal successful to main window
                      emit success();
                  }
              }
              

              To use signal and slots it seems to me that the following considerations should be taken into account:
              1- This way the workflow of procedure workers would be asynchronous I think. For example considering the code above, first a sendDataToSerial signal is emitted. Then from the corresponding slot in MainWindow the result of writing to serial port should be sent back to the procedure by emitting another signal. So the ProcAWorker would need to store its state i.e. what has been done (the first command has been sent) and what needs to be done (is waiting for the result of first write and also the second command needs to be sent). I think it should be implemented as a state machine, right? If that's the case then implementing complex procedures (like the procedure B I mentioned in my question) would be much more complicated.

              2- We need to send back the result of writing to or reading from serial port to the corresponding procedure. One workaround is to pass additional arguments like a flag (or a pointer) to the signal emitted from procedure workers (e.g. sendDataToSerial). What do you suggest?

              Additionally, If we use the signal/slot solution then I think it is better to create a serial worker and move that to a new thread as well, in order to keep the GUI (i.e. MainWindow) responsive.

              Also thanks for mentioning the leakage of serial_ .

              P.S.
              You mentioned that passing a class pointer to a class that contains that class is a wrong design. So I was wondering why is it done in Qt, i.e. when the QObject class (and its inherited classes from it) get a parent pointer argument? (actually the first argument of constructor of ProcAWorker is exactly this). How is it different?

              VRoninV Offline
              VRoninV Offline
              VRonin
              wrote on last edited by
              #6

              @mkaze said in Worker threads with shared resources in Qt application:

              Consider the code for ProcAWorker

              Using signal/slot it would become:

              void ProcAWorker::process()
              {
                  sendDataToSerial("Command a1");
                  QThread::sleep(1);
                  // perform some computations
                  sendDataToSerial("Command a2");
                  emit success();
              }
              

              If anything it's easier.
              Errors of serial write, again, are not a responsibility of the worker to handle. They should be handle by the object owning serial_

              "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

              M 1 Reply Last reply
              2
              • VRoninV VRonin

                @mkaze said in Worker threads with shared resources in Qt application:

                Consider the code for ProcAWorker

                Using signal/slot it would become:

                void ProcAWorker::process()
                {
                    sendDataToSerial("Command a1");
                    QThread::sleep(1);
                    // perform some computations
                    sendDataToSerial("Command a2");
                    emit success();
                }
                

                If anything it's easier.
                Errors of serial write, again, are not a responsibility of the worker to handle. They should be handle by the object owning serial_

                M Offline
                M Offline
                mkaze
                wrote on last edited by mkaze
                #7

                @VRonin said in Worker threads with shared resources in Qt application:

                @mkaze said in Worker threads with shared resources in Qt application:

                Consider the code for ProcAWorker

                Using signal/slot it would become:

                Thanks for your reply. That's right, but your code considers only write operations. A procedure may want to read from a serial port so it must wait (or be notified) when the response is ready. Even in case of only write operations, a procedure may want to perform some alternative operations or rollbacks when write errors happens. I meant something like the following when I mentioned implementing ProcAWorker as a state machine:

                ProcAWorker::ProcAWorker() :
                    current_state_(STATE_INITIAL),
                    next_state_(STATE1)
                {
                    // assign a unique id to this procedure to
                    // distinguish it from other procedures when
                    // communicating with serial worker
                    PID_ = PROCA_ID;
                    connect(this, &ProcAWorker::forward, this, &ProcAWorker::process);
                }
                
                void ProcAWorker::reset_states()
                {
                    current_state_ = STATE_INITIAL;
                    next_state_ = STATE1;
                }
                
                void ProcAWorker::process()
                {
                    current_state_ = next_state_;
                
                    switch (current_state_){
                
                    case STATE1:
                    {
                        emit serial_write_data(PID_, "command a1");
                        QThread::sleep(1);
                        next_state_ = STATE2;
                        break;
                    }
                
                    case STATE2:
                        emit serial_write_data(PID_, "command a2");
                        // perform some computations
                        next_state_ = STATE_FINAL;
                        break;
                
                    case STATE_FINAL:
                        emit success();
                        reset_states();
                        break;
                
                    default:
                        reset_states();
                        break;
                    }
                
                    return;
                }
                
                void ProcAWorker::serial_write_response(const Stepper::proc_id pid, bool response)
                {
                    // if the response does not belong
                    // to this procedure, ignore it
                    if (pid != PID_)
                        return;
                
                    if (response) {
                        emit forward();
                    } else {
                        emit error(ERROR_PORT_WRITE);
                        // update some internal variables
                
                        reset_states();
                    }
                }
                
                void ProcAWorker::serial_read_response(const Stepper::proc_id pid, const QByteArray & response)
                {
                    // if the response does not belong
                    // to this procedure, ignore it
                    if (pid != PID_)
                        return;
                    
                    // store response in a member variable for later use
                    // or perform some calculations and change some internal variables based on it
                    
                    emit forward();
                }
                
                }
                

                And on the other side, in serial worker we have:

                void SerialWorker::write_data(const proc_id pid, const QByteArray & data)
                {
                    serial_->write(data);
                    bool write_ok = serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
                    emit write_finished(pid, write_ok);
                }
                
                
                void SerialWorker::read_data(const proc_id pid)
                {
                    QByteArray data = serial_->readAll();
                    emit read_finished(pid, data);
                }
                
                // This slot is invoked when we want to read immediately after
                // writing a command on serial port. Essentially, we are
                // expecting a reponse to the sent command.
                void SerialWorker::write_read_data(const proc_id pid, const QByteArray & data)
                {
                    serial_->write(data);
                    bool write_ok = serial_->waitForBytesWritten(SERIAL_WRITE_TIMEOUT);
                    if (write_ok) {
                        serial_.waitForReadyRead(SERIAL_READ_TIMEOUT);
                        QByteArray response = serial_->readAll();
                        emit write_read_finished(pid, write_ok, reponse);
                    } else {
                        emit write_read_finished(pid, write_ok, QByteArray());
                    }
                
                }
                

                which the corresponding signals/slots have been connected in main thread (i.e. GUI thread) when creating ProcAWorker, ProcBWorker, ... and SerialWorker.

                What do you think about this design?

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

                  I agree you need to use a state machine for that case. http://doc.qt.io/qt-5/qstatemachine.html probably helps putting down the skeleton already

                  "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
                  2

                  • Login

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