Señales y Slots entre objetos en distintos hilos de ejecución



  • Básicamente tengo lo siguiente (salvando las distancias):

     class servidorTCP : public QObject
     {
          // métodos varios...
    
          signals:
               void nuevasInstrucciones(QJsonDocument jDoc);
    
          public slots:
               void respuestaObtenida(QJsonDocument jDoc);
     }
    
     class recolectorModbus : public QObject
     {
          // métodos varios...
    
          signals:
               void respuestaLista(QJsonDocument jDoc);
    
          public slots:
               void ejecutarInstruccion(QJsonDocument jDoc);
     }
    
     void main(int argc, char *argv[])
     {
          QCoreApplication a(argc, argv);
          int numeroRedes = 2;
          servidorTCP *servidor = new servidorTCP;
          recolectorModbus * recolecta = new recolectorModbus[numeroRedes];
          QThread * hilos = new QThread[numeroRedes];
    
          // más código necesario...
    
          for(int i = 0; i < numeroRedes; i++)
          {
               recolecta[i].moveToThread(hilos[i]);
    
               QObject::connect(&servidor, SIGNAL(nuevasInstrucciones(QJsonDocument)),
                                        &recolecta[i], SLOT(ejecutarInstruccion(QJsonDocument)));
    
               QObject::connect(&recolecta[i], SIGNAL(respuestaLista(QJsonDocument)),
                                        &servidor, SLOT(respuestaObtenida(QJsonDocument)));
    
               // Demás señales necesarias entre los objetos 'recolecta' y 'hilos'
    
               hilos[i].start();
          }
    
          a.exec();
     }
    

    El problema está en que las conexiones entre los objetos 'servidor' y 'recolecta' no funcionan. El objeto 'servidor' está en el mismo hilo que la función 'main' pero los objetos 'recolecta' se han movido a otros hilos de ejecución.

    ¿Qué tengo que hacer para que ambos objetos se puedan comunicar correctamente?

    El objetivo que persigo es que el 'servidor' sea capaz de enviar una señal a todos los objetos 'recolecta' que existan. En cada uno de los objetos 'recolecta' se ejecuta el slot y devuelvan al 'servidor' la respuesta si la hay.

    Si configuro la conexión para que sea del tipo Qt::Directconnection los Slots se ejecutan en el mismo hilo que la función 'main' y el objeto 'servidor' y eso no me interesa.

    Toda ayuda o sugerencia será agradecida.

    Un saludo a todos y disfrutad mucho del verano.



  • Resuelto.

    En el código anterior que había expuesto, se me olvidó comentar que existe un método en el que realizo el proceso principal de la clase dentro de un bucle "infinito". ¡E ahí el problema!

    Por lo tanto solo había que cambiar un par de detalles.

    Cuando se sabe qué tocar resulta fácil, hasta entonces te vuelves loco intentando averiguar qué falla.

     class recolectorModbus : public QObject
     {
          // métodos varios...
    
          signals:
               void respuestaLista(QJsonDocument jDoc);
    
          public slots:
               void ejecutarInstruccion(QJsonDocument jDoc);
    
          private:
               void miProceso()
               {
                    while(true)
                    {
                         // Write and read Serial Port
                         // Save data in json 
                    }
               }
     }
    

    Pasa a convertirse en:

     class recolectorModbus : public QObject
     {
          // métodos varios...
    
          signals:
               void respuestaLista(QJsonDocument jDoc);
    
          public slots:
               void ejecutarInstruccion(QJsonDocument jDoc);
    
          private:
               void miProceso()
               {
                    while(true)
                    {
                         // Write and read Serial Port
                         // Save data in json 
    
                         // New line:
                         QCoreApplication::processEvents(QEventLoop::AllEvents);
                    }
               }
     }
    

    En el main() hay que añadir la siguiente conexión:

    QObject::connect(&hilos[i], SIGNAL(start()), 
                                &recolecta[i], SLOT(miProceso()));
    

    Con esto consigo que al iniciarse el hilo de ejecución se ponga en marcha mi proceso.

    Con la nueva línea QCoreApplication::processEvents(QEventLoop::AllEvents); al final del bucle del proceso consigo que se ejecuten los eventos que se hayan producido en este hilo.

    No se si es la mejor solución, pero me funciona. Si alguien tiene una propuesta mejor, soy todo oidos.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.