2011-07-15 11 views
7

¿Cómo puedo despertar un QThread cuando está durmiendo?¿Despertar un QThread que está en reposo?

Tengo un hilo que se ejecuta en el fondo y de vez en cuando se despierta y hace algunas cosas pequeñas, sin embargo, si me gustaría detener ese hilo de forma controlada, tengo que esperar a que se despierte por él auto para hacerlo renunciar. Y dado que está durmiendo bastante tiempo, esto puede ser bastante molesto.

Aquí hay un pequeño código de ejemplo que muestra el problema básico.

Comencemos con el hilo que en este ejemplo duerme durante 5 segundos y luego solo imprime un punto.

#include <QDebug> 
#include "TestThread.h" 

void TestThread::run() 
{ 
    running = true; 
    while(running == true) 
    { 
     qDebug() << "."; 
     QThread::sleep(5); 
    } 
    qDebug() << "Exit"; 
} 

void TestThread::stop() 
{ 
    running = false; 
} 

Luego tenemos el principal que inicia el hilo y luego lo mata.

#include <QDebug> 
#include "TestThread.h" 

int main(int argc, char *argv[]) 
{ 
    qDebug() << "Start test:"; 
    TestThread *tt = new TestThread(); 

    tt->start(); 
    sleep(2); 
    tt->stop(); 
    tt->wait(); 

    delete tt;  
} 

El problema es que tt-> wait(); debe esperar los 5 segundos para que el hilo duerma. ¿Puedo llamar algo así como un "despertar del sueño" para que pueda continuar?

¿O hay una manera mejor de hacer esto?

/Gracias


actualización lo tengo trabajando con un QMutex y la trylock:

#include <QDebug> 
#include "TestThread.h" 

QMutex sleepMutex; 

void TestThread::run() 
{ 
    qDebug() << "Begin"; 
    //1. Start to lock 
    sleepMutex.lock(); 
    //2. Then since it is locked, we can't lock it again 
    // so we timeout now and then. 
    while(!sleepMutex.tryLock(5000)) 
    { 
     qDebug() << "."; 
    } 
    //4. And then we cleanup and unlock the lock from tryLock. 
    sleepMutex.unlock(); 
    qDebug() << "Exit"; 
} 

void TestThread::stop() 
{ 
    //3. Then we unlock and allow the tryLock 
    // to lock it and doing so return true to the while 
    // so it stops. 
    sleepMutex.unlock(); 
} 

Pero sería mejor utilizar el QWaitCondition? ¿O es lo mismo?


actualización: Los descansos QMutex si no es la misma banda de rodamiento que se inicia y lo detiene, asi que aquí hay una oportunidad con QWaitCondition.

#include <QDebug> 
#include <QWaitCondition> 
#include "TestThread.h" 

QMutex sleepMutex; 

void TestThread::run() 
{ 
    qDebug() << "Begin"; 

    running = true; 
    sleepMutex.lock(); 
    while(!waitcondition.wait(&sleepMutex, 5000) && running == true) 
    { 
     qDebug() << "."; 
    } 
    qDebug() << "Exit"; 
} 

void TestThread::stop() 
{ 
    running = false; 
    waitcondition.wakeAll(); 
} 

Respuesta

6

Se puede usar un QWaitCondition en lugar de un simple sleep. Si te da mucho más control.

Ejemplo de uso aquí: Wait Conditions Example

+0

Suena bien, pero ¿qué quieres decir? – Johan

+0

Mira el ejemplo que he vinculado. La idea es bloquear un mutex y usar la función 'wait (QMutex *, long)' de la condición de espera para reemplazar su suspensión, y usar 'wakeAll()' o 'wakeOne()' en su función 'stop()'. Su edición no es buena: no debe llamar 'lock()' desde un hilo y 'unlock()' desde otro en el mismo objeto mutex. – Mat

+0

Entonces nunca lo desbloqueas? ¿Mantiene el "bool funcionando" así que detenga el ciclo? – Johan

1

no creo que existe una solución portátil (aunque puede haber algunas instalaciones en algunos sistemas operativos, como señales POSIX). De todos modos, sí Qt no proporciona tales medios, por lo tanto se podía simular como si fuera

void TestThread::run() 
{ 
    running = true; 
    while(running == true) 
    { 
     qDebug() << "."; 
     // Quantize the sleep: 
     for (int i = 0; i < 5 && running; ++i) QThread::sleep(1); 
    } 
    qDebug() << "Exit"; 
} 

Pero la mejor solución seguiría siendo un QWaitCondition, como se ha señalado por Mat.

Cuestiones relacionadas