2009-11-03 2 views

risposta

30

Poiché è possibile partecipare a un thread anche dopo la sua chiusura, joinable() restituirà true finché non si chiama join() o detach(). Se vuoi sapere se un thread è ancora in esecuzione, dovresti essere in grado di chiamare timed_join con un tempo di attesa pari a 0. Nota che questo può causare una condizione di competizione poiché il thread potrebbe terminare subito dopo la chiamata.

+6

È un po 'fuorviante dire che può portare a una condizione di gara. 'timed_join' da solo non può farlo. se si formulano ipotesi errate in base al risultato della chiamata, è possibile che si verifichi una condizione di competizione, naturalmente, ma ciò non ha molto a che fare con 'timed_join' piuttosto che con voi assumendo che il risultato di tale chiamata sia ancora valido. Ad ogni modo, +1 – jalf

+35

Penso che sia davvero pessimo. Perché i designer di boost non pensano mai all'intuitività o ai principianti. Un semplice metodo isRunning() sarebbe stato sufficiente. Invece costringono uno a usare una funzione che non dovrebbe essere intuitivamente utilizzata in questo caso. Non voglio provare a partecipare al thread, voglio solo testare rapidamente se fa ancora qualcosa. Questa è una merda. Ho perso un sacco di tempo prima di aver trovato questo. Neanche una parola dannata nei "documenti". – AndreasT

+0

Un thread può essere in 3 stati: In esecuzione, Separato, NotRunning. –

3

Fondamentalmente non è possibile farlo. La ragione è che le due risposte possibili sono "Sì" e "Non quando ho guardato l'ultima volta ma forse ora". Non esiste un modo affidabile per determinare se un thread è ancora all'interno del suo metodo di esecuzione, anche se esistesse un modo affidabile per determinare l'opposto.

+7

Fondamentalmente _can_ fare questo. È possibile interrogare in modo affidabile o "osservare" lo stato di un thread in qualsiasi momento. Il problema è che non puoi fare alcuna ipotesi per le interazioni in base allo stato che hai recuperato, nel momento in cui hai le informazioni "il thread è ancora in esecuzione", potrebbe essere già stato interrotto nel tempo necessario per ottenere tali informazioni, ma questo è raramente critico. Scusate ma questo post non è stato in alcun modo utile. – AndreasT

+0

@AndreasT: Se non puoi fare ipotesi, come potrebbe essere utile? –

5

Utilizzare thread::timed_join() con un timeout minimo. Restituirà false se il thread è ancora in esecuzione.

+0

Questo è falso. Se un thread è stato rimosso, restituirà false. In effetti è necessario leggerlo al contrario: se restituisce true il thread era in esecuzione e poi si è fermato durante il timeout –

+0

@GaetanoMendola: Non esattamente, il thread potrebbe essere fermato e joinable quando si chiama timed_join e il risultato è true. –

0

Questo è un po 'grezzo, ma come di ora funziona ancora per le mie esigenze. :) Sto usando boost 153 e qt. Ho creato un vettore di int per tracciare lo "stato" dei miei thread. Ogni volta che creo un nuovo thread, aggiungo una voce a thread_ids con un valore pari a 0. Per ogni thread creato, trasmetto un ID in modo da sapere quale parte di thread_ids devo aggiornare. Imposta lo stato su 1 per l'esecuzione e altri valori in base all'attività che sto svolgendo, quindi so quale attività è stata eseguita al termine del thread. 100 è il valore che ho impostato per un thread correttamente finito. Non sono sicuro che ciò possa essere d'aiuto, ma se hai altri suggerimenti su come migliorare su questo fammelo sapere. :)

std::vector<int> thread_ids; 
const int max_threads = 4; 
void Thread01(int n, int n2) 
{ 
    thread_ids.at(n) = 1; 
    boost::this_thread::sleep(boost::posix_time::milliseconds(n2 * 1000)); 
    thread_ids.at(n) = 100; 
    qDebug()<<"Done "<<n; 

} 
void getThreadsStatus() 
{ 
    qDebug()<<"status:"; 
    for(int i = 0; i < max_threads, i < thread_ids.size(); i++) 
    { 
     qDebug()<<thread_ids.at(i); 
    } 
} 
int main(int argc, char *argv[]) 
{ 
    for(int i = 0; i < max_threads; i++) 
    { 
     thread_ids.push_back(0); 
     threadpool.create_thread(
      boost::bind(&boost::asio::io_service::run, &ioService)); 
     ioService.post(boost::bind(Thread01, i, i + 2)); 
     getThreadsStatus(); 
    } 

    ioService.stop(); 
    threadpool.join_all(); 
    getThreadsStatus(); 
} 
0

Il modo più semplice, se la funzione che esegue il thread è abbastanza semplice, è impostare una variabile su true al termine della funzione. Naturalmente, avrai bisogno di una variabile per thread, se hai molti una mappa di ID di thread e lo stato può essere un'opzione migliore. So che è fatto a mano, ma nel frattempo funziona bene.

class ThreadCreator 
{ 
private: 
    bool   m_threadFinished; 
    void launchProducerThread(){ 
     // do stuff here 
     m_threadRunning = true; 
    } 
public: 
    ThreadCreator() : m_threadFinished(false) { 
     boost::thread(&Consumer::launchProducerThread, this); 
    } 
}; 
0

Questo non può essere una risposta diretta alla sua domanda, ma vedere il concetto filo come meccanismo realmente leggero e volutamente privo di qualsiasi cosa tranne meccanismi di sincronizzazione. Penso che il posto giusto per mettere "sia in esecuzione" sia nella classe che definisce la funzione thread. Si noti che dal punto di vista del design, è possibile uscire dal thread su interrupt e non completare il lavoro. Se vuoi ripulire il thread una volta completato, puoi inserirlo in un puntatore sicuro e passarlo alla classe worker.

+0

Credo che sarebbe meglio se chiarisci con esempi di codice e dividi il tuo testo in paragrafi per facilitare la leggibilità. – phaberest