2011-03-01 25 views
6

Cuándo usamos cada una de estas llamadas de función en una aplicación de subprocesos. teniendo en cuenta dos funciones fun1() y fun2() definidas en la misma clase que tratan con la lectura/escritura de datos en búferes (operación de cola). para lograr multi-threading a estos. tendríamos que ejecutar las dos funciones en un hilo separado. ahora digamos que la primera lectura de la función se llama al comienzo de su hilo.Qt moveToThread() vs llamada nueva cadena cuando usamos cada

es mejor usar moveTothread (segundo hilo) para función de escritura en el inicio de la primera funciones hilo

O

definen la segunda función en una nueva enhebrar clase y llamar a ese hilo al al comienzo del primer hilo.

+0

relacionado: [Aplicación principal QThread blocking] (http://stackoverflow.com/questions/3213738/) –

Respuesta

8

Usando moveToThread podemos cambiar la afinidad del hilo de un objeto. Lo que OP pregunta es cómo podemos ejecutar dos funciones de la misma clase en diferentes hilos.

clase A y dos funciones

Let f1 y f2

class A 
{ 
public: 
    void f1(); 
    void f2(int i); 
    void run(); // shows how we can trigger f1 and f2 in different threads 
} 

Qt ya proporcionan una clase para ejecutar funciones en diferentes temas y se llama QtConcurrentRun

La función QtConcurrent::run() ejecuta una función en una hilo separado El valor de retorno de la función está disponible a través de la API QFuture .

La función que se activa puede ser una función externa o una función de miembro. Por lo que en nuestro caso si queríamos desde el objeto en sí mismo para comenzar f1 y f2 en diferentes hilos que podíamos hacer lo siguiente en run()

void run() 
{ 
    // QFuture<void> because f1 is void 
    QFuture<void> future1 = QtConcurrent::run(this, &A::f1); 
    int k = 5; // Concurrent run with arguments 
    QFuture<void> future2 = QtConcurrent::run(this, &A::f2, k); 
} 

Del mismo modo se podría ejecutar cualquier función pública de cualquier clase al mismo tiempo, por ejemplo

QImage image = ...; 
QFuture<void> future = QtConcurrent::run(image, &QImage::invertPixels, QImage::InvertRgba); 

A a; 
QFuture<void> future1 = QtConcurrent::run(A, &A::f1); 

cuenta de la diferencia entre las dos llamadas:

QtConcurrent::run() también acepta punteros a functi miembro ons. El primer argumento debe ser una referencia constante o un puntero a una instancia de la clase . La referencia Passing by const es útil cuando llama a las funciones miembro de const; pasar por puntero es útil para llamando a funciones miembro no constantes que modifican la instancia.

Con el fin de comprobar cuándo ha finalizado una función ejecutada simultáneamente debe utilizar un QFutureWatcher.

9

Me gusta Piotr respondió que realmente debería echar un vistazo al enlace que sugirió.
Como entiendo su problema, eso debería resolver su problema.
Este es el código simplificado de ese blog:

class Producer 
{ 
public: 
    Producer(); 

public slots: 
    void produce() 
    { //do whatever to retrieve the data 
     //and then emit a produced signal with the data 
     emit produced(data); 
     //if no more data, emit a finished signal 
     emit finished(); 
    } 

signals: 
    void produced(QByteArray *data); 
    void finished(); 
}; 

class Consumer 
{ 
public: 
    Consumer(); 

public slots: 
    void consume(QByteArray *data) 
    { 
     //process that data 
     //when finished processing emit a consumed signal 
     emit consumed(); 
     //if no data left in queue emit finished 
     emit finished(); 
    } 
}; 

int main(...) 
{ 
    QCoreApplication app(...); 

    Producer producer; 
    Consumer consumer; 

    producer.connect(&consumer, SIGNAL(consumed()), SLOT(produce())); 
    consumer.connect(&producer, SIGNAL(produced(QByteArray *)), SLOT(consume(QByteArray *)); 

    QThread producerThread; 
    QThread consumerThread; 
    producer.moveToThread(&producerThread); 
    consumer.moveToThread(&consumerThread); 

    //when producer thread is started, start to produce 
    producer.connect(&producerThread, SIGNAL(started()), SLOT(produce())); 

    //when consumer and producer are finished, stop the threads 
    consumerThread.connect(&consumer, SIGNAL(finished()), SLOT(quit())); 
    producerThread.connect(&producer, SIGNAL(finished()), SLOT(quit())); 

    producerThread.start(); 
    consumerThread.start(); 

    return app.exec(); 
} 
+0

Esta fue una referencia perfecta para el problema que estaba tratando de resolver. Buen enfoque idiomático de Qt. La única modificación que hice fue desacoplar la señal 'consumida()' de la ranura 'producir()' y conectar la señal 'finished()' del productor con la señal 'finished()' del consumidor. De esta forma, el productor no espera al consumidor y notifica al consumidor cuándo es seguro dejarlo. – russdot

Cuestiones relacionadas