2011-07-15 3 views
7

Comment puis-je réveiller un QThread lorsqu'il dort? J'ai un thread qui fonctionne en arrière-plan et qui se réveille de temps en temps et fait de petites choses, mais si je veux arrêter ce thread de manière contrôlée, je dois attendre qu'il se réveille par lui soi-même afin de le faire quitter. Et comme il dort assez longtemps, cela peut être assez ennuyeux.Réactiver un QThread en veille?

Voici un petit exemple de code qui montre le problème de base.

Commençons par le fil qui, dans cet exemple, dort pendant 5 secondes, puis imprime simplement un point. Ensuite, nous avons le principal qui démarre le thread et le tue. Ensuite, nous avons le principal qui démarre le thread.

#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;  
} 

Le problème est que le tt-> wait(); doit attendre les 5s que le fil dorme. Puis-je appeler quelque chose comme un "réveil de sommeil" afin qu'il puisse continuer.

Ou y a-t-il une meilleure façon de faire cela?

/Merci


Mise à jour Je l'ai travaillé avec un QMutex et 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(); 
} 

Mais serait-il préférable d'utiliser le QWaitCondition? Ou est-ce le même?


Mise à jour: Les pauses QMutex si elle est pas la même bande de roulement qui commence et l'arrêter, alors voici est un essai avec 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(); 
} 

Répondre

6

Vous pouvez utiliser un QWaitCondition plutôt qu'un sleep simple. Si vous donne beaucoup plus de contrôle.

Exemple d'utilisation ici: Wait Conditions Example

+0

Ça a l'air bien, mais comment voulez-vous dire? – Johan

+0

Regardez l'exemple que j'ai lié. L'idée est de verrouiller un mutex et d'utiliser la fonction wait (wait (QMutex *, long)) pour remplacer votre sleep, et d'utiliser 'wakeAll()' ou 'wakeOne()' dans votre fonction 'stop()'. Votre édition n'est pas bonne: vous ne devriez pas appeler 'lock()' d'un thread et 'unlock()' d'un autre sur le même objet mutex. – Mat

+0

Alors vous ne le débloquez jamais? Vous gardez le "bool running" alors arrêtez la boucle? – Johan

1

Je ne pense pas qu'une solution portable existe (mais il pourrait y avoir des installations dans certains systèmes d'exploitation, comme des signaux POSIX). Quoi qu'il en soit, Qt lui-même ne fournit pas de tels moyens, vous pouvez ainsi simuler comme

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"; 
} 

Mais la meilleure solution serait encore un QWaitCondition, comme l'a souligné Mat.