Pregunta

En mi aplicación está el hilo principal y un hilo de trabajo ( QThread ).
Desde el hilo principal me gustaría invocar un método de mi hilo de trabajo y hacer que se ejecute en el contexto del hilo.

He intentado usar QMetaObject :: invokeMethod y le doy la opción QueuedConnection pero no funciona.
También intenté emitir señales desde el subproceso principal (que está conectado a la ranura del subproceso de trabajo) pero eso también falló.

Aquí hay un fragmento de aproximadamente lo que probé:

class Worker : public QThread
{
    Q_OBJECT

public:
    Worker() { }

    void run() 
    { 
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        exec(); 
    }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

Usando la forma QMetaObject:

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    QMetaObject::invokeMethod(&worker, "doWork", Qt::QueuedConnection);

    return a.exec();
}

Usando la señal:

class Dummy : public QObject
{
    Q_OBJECT

public:
    Dummy() { }

public slots:
    void askWork() { emit work(); }

signals:
    void work();
};

int main(int argc, char *argv[])
{
    QCoreApplication a(argc, argv);

    qDebug() << "main thread id - " << QThread::currentThreadId();

    Worker worker;
    worker.start();

    Dummy dummy;
    QObject::connect(&dummy, SIGNAL(work()), &worker, SLOT(doWork()), Qt::QueuedConnection);

    QTimer::singleShot(1000, &dummy, SLOT(askWork()));

    return a.exec();
}

En ambos sentidos, la identificación del hilo principal se imprime en el QThread doWork .

Además, pensé en implementar un simple productor-consumidor, pero si esto funciona, ¿hay alguna razón para no hacerlo de esta manera?

¿Fue útil?

Solución

El problema era que el receptor (el QThread) 'vive' en el hilo principal y, por lo tanto, el bucle de eventos del hilo principal es el que ejecuta la ranura.

de los documentos de Qt:

  

Con las conexiones en cola, la ranura se invoca cuando el control vuelve al bucle de eventos del hilo al que pertenece el objeto. La ranura se ejecuta en el hilo donde vive el objeto receptor.

Entonces, la solución que encontré hasta ahora fue crear un objeto dentro de la ejecución del hilo () y usar sus ranuras en su lugar. De esta forma, el propietario del receptor es el hilo y luego se llama a la ranura en el contexto de hilos.

Otros consejos

Este ejemplo muestra cómo puede dividir la clase Worker para que funcione como desee. También debe poner a disposición una referencia o puntero a la instancia de Worker para poder conectarse a la ranura.

class Worker : public QObject
{
    Q_OBJECT

public:
    Worker() { }

public slots:
    void doWork()
    {
        qDebug() << "executing thread id - " << QThread::currentThreadId();
    }
};

class WorkerThread : public QThread
{
    Q_OBJECT

public:
    void run()
    {
        qDebug() << "new thread id " << QThread::currentThreadId(); 
        Worker worker;
        exec();
    }
};

Para el ejemplo simple productor-consumidor, eche un vistazo a la entrada del blog de Bradley T. Hughes Pisando sin dolor de cabeza .

El trabajador se crea en el hilo principal y, por lo tanto, sus eventos se procesan en el hilo principal. Debe mover al trabajador a su propio hilo:

Worker worker;
worker.moveToThread(&worker);
worker.start();

Ahora Qt sabe que trabajador vive en el nuevo hilo y pondrá en cola los eventos en ese bucle de eventos.

Parece que su hilo de trabajo se completa antes de que pueda invocar cualquier función o enviarle una señal.

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