Pregunta

La documentación de

Qt establece que las señales y las ranuras pueden ser directa , en cola y auto .

También indicó que si el objeto que posee la ranura 'vive' en un hilo diferente del objeto que posee la señal, la emisión de dicha señal será como publicar un mensaje: la emisión de la señal regresará instantáneamente y se llamará al método de ranura en el bucle de eventos del hilo objetivo .

Desafortunadamente, la documentación no especifica que 'vidas' significa y no hay ejemplos disponibles. He intentado el siguiente código:

main.h:

class CThread1 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        msleep( 200 );
        std::cout << "thread 1 started" << std::endl;
        MySignal();
        exec();
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

main.cpp:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & oThread2, SLOT( MySlot() ) );
    oThread1.start();
    oThread2.start();
    oThread1.wait();
    oThread2.wait();
    return a.exec();
}

La salida es:

thread 2 started
thread 1 started

MySlot () nunca se llama :(. ¿Qué estoy haciendo mal?

¿Fue útil?

Solución

Hay bastantes problemas con su código:

  • como dijo Evan, falta la palabra clave emitir
  • todos sus objetos viven en el hilo principal, solo el código en los métodos de ejecución vive en otros hilos, lo que significa que la ranura de MySlot se llamaría en el hilo principal y no estoy seguro de que eso sea lo que quiere
  • nunca se llamará a su ranura, ya que el bucle de eventos principal nunca se iniciará: sus dos llamadas a esperar () solo se agotarán después de un tiempo muy largo (y probablemente matará su aplicación antes de que eso suceda) y no lo haga. tampoco pienses que eso es lo que quieres, de todos modos realmente no tienen uso en tu código.

Es muy probable que este código funcione (aunque no lo he probado) y creo que hace lo que quieres que haga:

class MyObject : public QObject
{
    Q_OBJECT
public slots:
    void MySlot( void )
    {
        std::cout << "slot called" << std::endl;
    }
};

class CThread1 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 1 started" << std::endl;
        int i = 0;
        while(1)
        {
           msleep( 200 );
           i++;
           if(i==1000)
              emit MySignal();
        }
    }
signals:
    void MySignal( void );
};

class CThread2 : public QThread
{
    Q_OBJECT
public:
    void run( void )
    {
        std::cout << "thread 2 started" << std::endl;
        exec();
    }
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);
    CThread1 oThread1;
    CThread2 oThread2;
    MyObject myObject;
    QObject::connect( & oThread1, SIGNAL( MySignal() ),
        & myObject, SLOT( MySlot() ) );
    oThread2.start();
    myObject.moveToThread(&oThread2)
    oThread1.start();
    return a.exec();
}

Ahora MyObject vivirá en thread2 (gracias a moveToThread).

MySignal debe enviarse desde el hilo 1 (aunque no estoy seguro de eso, podría enviarse desde el hilo principal, en realidad no importa).

No se necesita ningún bucle de eventos en el hilo 1 ya que la emisión de una señal no necesita un bucle de eventos. Se necesita un bucle de evento en thread2 (lanzado por exec ()) para recibir la señal.

MySlot se llamará en thread2.

Otros consejos

No subclase QThread para Qt 4.4+

Si bien la respuesta de Aiua es buena, quiero señalar algunos problemas con QThread y Qt 4.6 o 4.7.

Este artículo lo resume: http: / /blog.qt.io/blog/2010/06/17/youre-doing-it-wrong/

Falta de documentación por parte de Qt

Lamentablemente, el problema se debe a la falta de actualizaciones de la documentación. Antes de Qt 4.4, QThread no tenía una implementación run () predeterminada, lo que significaba que tenía que subclasificar QThread para poder usarlo.

Si está utilizando Qt 4.6 o 4.7, entonces seguramente no subclase QThread.

Usar moveToThread

La clave para que las ranuras se ejecuten en un subproceso de trabajo es utilizar el método moveToThread como señaló Aiua.

debe emitir la señal para iniciar su función de hilo como

emit operateCut(examId,examName_examTemplate[examName].studentIdRec,examName_examTemplate[examName].choiceRecA,examName_examTemplate[examName].choiceRecB,examName_examTemplate[examName].objectRecA,examName_examTemplate[examName].objectRecB);

puede agregar más de un argumento en esta señal

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top