2013-06-11 1 views
9

Voici le code de mon implémentation qthread. J'essaie d'obtenir des données GPS par satellite. QThread ne produit pas le signal finished() même lorsque les programmes sortent de la fonction de logement gpsSearch(). La fonction locateMe() est appelée à chaque fois qu'un bouton est cliqué. La première fois que le thread n'est pas démarré et que le bouton est cliqué, il imprime la vraie valeur pour la fonction isRunning() et imprime la valeur false pour la fonction isFinished(). J'ai dû appeler la fonction quit() de QTherad pour arrêter manuellement le fil. Après cela, il va à la fonction threadQuit() connecté dans la classe gnssProvider. Mais même après cela, si je clique sur le bouton, il imprime la vraie valeur pour isRunning et false pour isFinished() dans la fonction locateMe().QThread émet un signal finished() mais isRunning() renvoie true et isFinished() renvoie la valeur false

GPSInfo::GPSInfo() 
{ 
    hybridGPSFound = satelliteGPSFound = networkGPSFound = false; 
    qDebug()<<"Thread Creating"; 
    gnssThread = new QThread; 
    gnssProvider = new LocationFetcher(this,GEOLOCATION_PROVIDER_GNSS,1); 
    gnssProvider->moveToThread(gnssThread); 
    connect(gnssThread, SIGNAL(started()), gnssProvider, SLOT(gpsSearch())); 
    connect(gnssThread, SIGNAL(finished()), gnssProvider, SLOT(threadQuit())); 
} 
void LocationFetcher::gpsSearch() 
{ 
    if (BPS_SUCCESS != geolocation_request_events(0)) 
    { 
     fprintf(stderr, "Error requesting geolocation events: %s", strerror(errno)); 
     return; 
    } 
    geolocation_set_provider(GPS_Search_Provider); 
    geolocation_set_period(GPS_Search_Period); 
    while (!stopThread) 
    { 
     bps_event_t *event = NULL; 
     bps_get_event(&event, -1); 

     if (event) 
     { 
      if (bps_event_get_domain(event) == geolocation_get_domain() && bps_event_get_code(event) == GEOLOCATION_INFO) 
      { 
       handle_geolocation_response(event); 
       break; 
      } 
     } 
    } 
    geolocation_stop_events(0); 

    this->quit(); 

} 
void GPSInfo::LocateMe() 
{ 
    qDebug()<<"Thread Running: "<<gnssThread->isFinished(); 
    qDebug()<<"Thread Running: "<<gnssThread->isRunning(); 

    gnssThread->start(); 
    hybridThread->start(); 
    networkThread->start(); 

} 
+3

Etes-vous sûr que vous n'avez pas mélangé isFinished et isRunning? Vous avez '" Thread Running: "' dans les deux lignes. –

+0

Non, je n'ai pas :) J'étais trop paresseux pour résoudre ce problème: P – Tahlil

+1

pouvez-vous poster l'exemple complet? Peut-être le fil n'a pas fini –

Répondre

27

La façon dont fonctionne le cycle de vie QThread est comme ceci:

  1. Vous appelez QThread::start().
  2. À ce stade, isRunning() doit commencer à renvoyer true.
  3. Les composants internes du fil commencent. Ils émettent le signal started(). Les composants internes du fil appellent run().
  4. Sauf si vous remplacez cela dans une sous-classe, run() appelle exec().
  5. exec() entre dans une boucle d'événement et y reste jusqu'à ce que quit() ou exit() soit appelée.
  6. exec() et run() revenir aux internes.
  7. À ce stade, isFinished() doit commencer à renvoyer true et isRunning() false. Les signaux internes émettent le signal finished().
  8. Les composants internes effectuent certains nettoyages finaux.
  9. Le thread se termine pour de vrai.

Vous avez donc besoin d'appeler quit() après votre position fetcher est fait - mais this->quit() ne demande pas quit() sur le fil! C'est probablement pourquoi ça ne fait rien.

Votre code ressemble un peu comme il a été calqué sur cet article:

http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/

note comment elle donne son travailleur un signal finished() (pas le même que QThread::finished) et se connecte à la fente QThread::quit().

+0

Ce message est la bonne réponse. Je voudrais seulement ajouter que nous devons en savoir plus sur l'emplacement threadQuit pour en dire plus. Si cet emplacement supprime le fil, il me semble que vous pourriez avoir un pointeur qui pend. – Phlucious

+0

Merci beaucoup pour avoir une meilleure compréhension de QThread :) – Tahlil

+0

Une réponse très complète, difficile à trouver ailleurs. – Trilarion

1

Il est prévu que le thread ne se ferme pas tant que vous ne l'avez pas terminé manuellement. L'objet thread héberge une boucle d'événement, donc il ne termine pas jusqu'à ce que la boucle d'événement se ferme, comme Sebastian l'a expliqué. En bref, vos connexions de fente de signal sont rétrogrades conceptuellement - l'objet devrait terminer le fil quand il a fini de faire sa chose, et non l'inverse.

0

Quelle version de Qt utilisez-vous?

Qt 4.8 a renvoyé des valeurs erronées jusqu'à la version 4.8.4 (bug Qt 30251). Ce bug a été corrigé en 4.8.5.

Questions connexes