2009-12-14 12 views
15

Recentemente, mi sono imbattuto in questo problema come ho memtionato in questo titolo. Ho provato usando QThread :: terminate(), ma non posso semplicemente fermare il thread, che è in un ciclo morto (diciamo, mentre (1)).Come posso terminare un QThread

grazie mille.

+0

rimarcato aggiungere il nome più comune "qt". – ChrisV

+2

Il doc Qt dice: "Attenzione: questa funzione è pericolosa e il suo utilizzo è sconsigliato Il thread può essere terminato in qualsiasi punto del suo percorso di codice.I thread possono essere terminati durante la modifica dei dati.Non c'è possibilità per il thread di ripulire dopo in sé, sblocca qualsiasi mutex trattenuto, ecc. In breve, usa questa funzione solo se assolutamente necessario. La terminazione può essere abilitata o disabilitata in modo esplicito chiamando QThread :: setTerminationEnabled(). Chiamando questa funzione mentre la terminazione è disabilitata, la terminazione viene differita, fino alla riattivazione della terminazione. " –

risposta

0

Hai provato exit o quit?

+0

quote da QT help doc: "Questa funzione non fa nulla se il thread non ha un ciclo di eventi" Potrebbe funzionare, nel caso di un ciclo di eventi. Ma se voglio terminarlo prima che il thread finisca il suo lavoro, come devo fare? grazie mille. Mio caro. – user230938

+0

Infatti queste 2 funzioni sono effettivamente utilizzate per tornare da un loop di eventi quando viene chiamato exec. –

0

Il thread ha chiamato QThread::setTerminationEnabled(false)? Ciò farebbe ritardare indefinitamente la terminazione del thread.

EDIT: Non so su quale piattaforma ci si trova, ma ho controllato l'implementazione di Windows di QThread :: terminate. Supponendo che il thread fosse effettivamente in esecuzione per cominciare, e la terminazione non è stata disabilitata tramite la funzione sopra, è fondamentalmente un wrapper attorno all'API di Windows TerminateThread(). Questa funzione accetta la mancanza di rispetto da nessun thread e tende a lasciare un disastro dietro con perdite di risorse e stato penzolante simile. Se non si sta uccidendo il thread, si ha a che fare con le chiamate del kernel zombie (molto probabilmente con I/O bloccato) o si hanno problemi ancora più grandi da qualche parte.

+0

No, e sono sicuro che il thread può essere terminato. Grazie. – user230938

+0

e lo faccio chiamare setTerminationEnabled (true); – user230938

12

Terminare il thread è la soluzione facile per arrestare un'operazione asincrona, ma di solito è una cattiva idea: il thread potrebbe fare una chiamata di sistema o potrebbe essere nel mezzo dell'aggiornamento di una struttura di dati quando viene interrotta, che potrebbe lasciare il programma o anche il sistema operativo in uno stato instabile.

Prova a trasformare il tuo while (1) in while (isAlive()) e make isAlive() restituisce false quando vuoi che il thread esca.

+0

Ciao, rpg. L'esempio di while (1) è solo un caso. Quello che voglio veramente è terminare il thread che sta facendo un pesante calcolo che durerà molto a lungo. Voglio solo fermarlo prima che finisca l'escuzione. Grazie. ps: ho visto un indizio che Rocknroll ha fornito --use pipe per fermare un Qthread. Ma non ho mai trovato la soluzione. – user230938

+0

Prova ad aggiungere qualcosa di simile ai punti di interruzione nella tua funzione di calcolo pesante: http://www.justsoftwaresolutions.co.uk/threading/thread-interruption-in-boost-thread-library.html – rpg

+0

Sì, sono d'accordo con ciò che viene detto Qui. Terminare una discussione a maniere difficile non è mai una buona cosa. –

0

Per utilizzare pipe senza nome

int gPipeFdTest[2]; //create a global integer array 

Come quando dove si intende creare tubi utilizzare

if(pipe(gPipeFdTest) < 0) 

{ 

perror("Pipe failed"); 

exit(1); 

} 

Il codice precedente creerà un tubo che presenta due estremità gPipeFdTest [0] per la lettura e gPipeFdTest [1] per la scrittura. Quello che puoi fare è impostare la funzione di corsa per leggere la pipe usando select system call. E da dove si vuole uscire di corsa, ci si prepara a scrivere usando la chiamata di sistema di scrittura. Ho usato una chiamata di sistema selezionata per monitorare l'estremità letta della pipa come meglio si adatta alla mia implmentazione. Cerca di capire tutto questo nel tuo caso. Se hai bisogno di ulteriore aiuto, dammi un ronzio.

Modifica:

Il mio problema era proprio come il tuo. Ho avuto un ciclo while (1) e le altre cose che ho provato erano necessarie mutex e altri fantasiosi mumbo jumbo multithreading, che aggiungevano complessità e debugging era un incubo. L'uso dei tubi mi ha assolto da quelle complessità, oltre a semplificare il codice. Non sto dicendo che sia l'opzione migliore, ma nel mio caso si è rivelata l'alternativa migliore e più pulita. Sono stato intercettato dalla mia applicazione sospesa prima di questa soluzione.

0

QThreads può deadlock se terminano "naturalmente" durante la terminazione.

Ad esempio in Unix, se il thread è in attesa di una chiamata "read", il tentativo di terminazione (un segnale Unix) farà interrompere la chiamata "read" con un codice di errore prima che il thread venga distrutto.

Ciò significa che il thread può ancora raggiungere il punto di uscita naturale mentre viene terminato. Quando lo fa, viene raggiunto un deadlock poiché un mutex interno è già bloccato dalla chiamata "terminate".

Per risolvere il problema, verificare che il thread non sia mai restituito se è stato terminato.

while(read(...) > 0) { 

    // Do stuff... 
} 

while(wasTerminated) 
    sleep(1); 

return; 

wasTerminated qui è in realtà implementato un po 'più complesso, utilizzando int atomiche:

enum { 

    Running, Terminating, Quitting 
}; 

QAtomicInt _state; // Initialized to Running 

void myTerminate() 
{ 
    if(_state.testAndSetAquire(Running, Terminating)) 
    terminate(); 
} 

void run() 
{ 
    [...] 

    while(read(...) > 0) { 

    [...] 
    } 

    if(!_state.testAndSetAquire(Running, Quitting)) { 
    for(;;) sleep(1); 
    } 
} 
Problemi correlati