2013-06-11 32 views
9

Di seguito è riportato il codice per la mia implementazione qthread. Sto cercando di ottenere i dati GPS dal satellite. QThread non produce il segnale finished() anche quando i programmi escono dalla funzione slot gpsSearch(). La funzione locateMe() viene richiamata ogni volta che si fa clic su un pulsante. La prima volta che il thread non viene avviato e si fa clic sul pulsante, viene stampato il valore vero per la funzione isRunning() e viene stampato il valore falso per la funzione isFinished(). Ho dovuto chiamare la funzione quit() di QTherad per interrompere manualmente il thread. Dopodiché passa alla funzione threadQuit() connessa nella classe gnssProvider. Ma anche dopo, se clicco sul pulsante, stampa vero valore per isRunning e false per isFinished() nella funzione locateMe().QThread emette il segnale finished() ma isRunning() restituisce true e isFinished() restituisce 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

Sei sicuro che non hai confuso isFinished e isRunning? Hai '" Thread Running: "' in entrambe le righe. –

+0

No, non l'ho fatto :) Ero troppo pigro per risolvere il problema: P – Tahlil

+1

puoi pubblicare un esempio completo? Forse thread non ha finito –

risposta

27

Il modo in cui il ciclo di vita QThread funziona è come questo:

  1. Si chiamano QThread::start().
  2. A questo punto, isRunning() dovrebbe iniziare a restituire true.
  3. Iniziano i thread interni. Emettono il segnale started().
  4. Gli interni del thread chiamano run().
  5. Se non si esegue l'override in una sottoclasse, le chiamate run()exec().
  6. exec() entra in un ciclo di eventi e rimane lì fino a quando quit() o exit() viene chiamato.
  7. exec() e run() ritorno alla parte interna.
  8. A questo punto, isFinished() dovrebbe iniziare a restituire true e isRunning() false.
  9. I componenti interni emettono il segnale finished().
  10. Gli interni eseguono alcune pulizie finali.
  11. Il thread termina per reale.

quindi è necessario chiamare quit() dopo la posizione Fetcher è fatto - ma this->quit() non sta chiamando quit() sul filo! Questo è probabilmente il motivo per cui non sta facendo nulla.

il codice sia un po 'come è stato modellato dopo questo articolo:

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

Nota come lei dà il suo lavoratore un segnale finished() (non lo stesso QThread::finished) e lo collega allo slot QThread::quit().

+0

Questo post è la risposta corretta. Vorrei solo aggiungere che abbiamo bisogno di sapere di più sullo slot threadQuit per aggiungere altro. Se quello slot cancella il thread, mi sembra che tu possa avere un puntatore pendente. – Phlucious

+0

Grazie mille per una migliore comprensione di QThread :) – Tahlil

+0

Una risposta molto completa, difficile da trovare altrove. – Trilarion

1

Si intende che il thread non si chiude finché non lo si termina manualmente. L'oggetto thread ospita un ciclo di eventi, quindi non termina finché il ciclo di eventi non si chiude, come ha spiegato Sebastian.

In breve, le connessioni dello slot di segnale sono concettualmente all'indietro - l'oggetto dovrebbe terminare il thread quando ha finito di fare la sua cosa, non il contrario.

0

Quale versione Qt usi?

Qt 4,8 ha restituito valori errati fino a 4.8.4 (Qt bug 30251). Questo bug è stato corretto in 4.8.5.