2009-08-01 11 views
5

En mi aplicación existe el hilo principal y un hilo de trabajo (QThread).
Del hilo principal me gustaría invocar un método de mi hilo de trabajo y ejecutarlo en el contexto del hilo.Invocando métodos en el contexto de QThread

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

He aquí un fragmento de aproximadamente lo que he intentado:

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(); 
    } 
}; 

Utilizando el camino 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(); 
} 

El uso de la forma de 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(); 
} 

Ambos caminos conducen a la principal ID de hilo impreso en QThreaddoWork.

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

Respuesta

3

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

de docs de Qt:

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

Así que 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 el espacio en el contexto de los hilos.

0

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

+1

el subproceso de trabajo está en su bucle de evento debido a la llamada a exec() –

2

Este ejemplo muestra cómo se puede dividir la clase Worker para que funcione como lo desee. También debe hacer disponible una referencia o un 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(); 
    } 
}; 
1

El trabajador se crea en el hilo principal, y por lo tanto es eventos se ha procesado en el hilo principal. Debe mover el trabajador a su propio hilo:

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

Ahora Qt sabe worker vidas en el nuevo hilo, y pondrá en cola eventos en que bucle de eventos.

Cuestiones relacionadas