2010-05-17 10 views
15

Ho un'applicazione che esegue alcune attività in background (lettura di rete & in lettura) in un numero Thread separato. Sembra comunque che il thread non venga terminato/interrotto quando chiudo l'applicazione (fai clic sul pulsante "x" sulla barra del titolo). È perché la routine Thread principale è while(true) {...}? Qual è la soluzione qui? Stavo cercando un flag di "interruzione" per il Thread come condizione per il ciclo "while", ma non ne ho trovato nessuno.Il thread non si interrompe alla chiusura dell'applicazione

risposta

21

Il modo più semplice è impostare la proprietà IsBackground su true. Ciò impedirà di mantenere l'applicazione aperta. Un'applicazione termina quando tutti i thread non di sfondo terminano.

Un modo più controllato per interrompere il thread è inviarlo un messaggio per arrestarlo in modo pulito e assicurarsi che sia stato terminato prima di terminare il thread principale.

Un metodo che non consiglierei è di chiamare Thread.Abort. Questo ha un numero di problemi, uno dei quali è che non è garantito per terminare il thread. Dalla documentazione:

Chiamare questo metodo in genere termina la discussione.

Enfasi mia.

+1

+1 al metodo messaggio.'while (stayAlive)' invece di 'true' è molto più pulito, anche se potenzialmente occorrono alcuni secondi in più affinché il ciclo si risolva. – user7116

0

Bene, invece di while(true), forse si dovrebbe:

while(appIsRunning) 
{ 
} 

E, durante l'evento di chiusura per il modulo,

appIsRunning = false; 
thread.Join(2000); 

in cui l'ultima riga è solo per assicurarsi che si attende per il filo per finire in modo pulito. Ci sono molti altri modi per forzare la fine di un thread, ma il problema è proprio lì: non vuoi essere forzando le cose, vuoi che succedano nel modo più naturale possibile.

Dopo il join, è possibile controllare lo stato del thread per vedere se è finito. In caso contrario, quindi (e solo successivamente) forzare la sua conclusione con una interruzione, e magari notificare all'utente (o scrivere un record di log) che qualcosa non è terminato come dovrebbe.

+0

Sì, ma ricordarsi di usare 'volatile' o' lock' o qualche altro metodo di sincronizzazione. –

+0

@Mark: potrebbe essere completamente sbagliato qui, ma poiché il thread figlio legge solo e il thread principale scrive solo, c'è una possibilità per un bug? –

+1

Senza la sincronizzazione non è garantito che una modifica di appIsRunning da un thread sarà visibile nell'altro thread. Puoi leggere di più qui: http://timl.net/2009/03/volatile-memory.html –

1

Si potrebbe migliorare la (vera) ciclo while per

void DoWork() { 
    while(!ShouldIQuitManualResetEvent.WaitOne(0)) { 
     // do something 
    } 
    IDidQuitManualResetEvent.Set() 
} 

Un po 'più elegante, a breve dai nomi identificatore.

3

È sempre possibile forzare la questione:

class Program 
{ 
    public static void Main() 
    { 
     // ... do stuff 
     Environment.Exit(Environment.ExitCode); 
    } 
} 

L'approccio migliore è quello di impostare la proprietà Thread.IsBackground al vero come Mark già accennato.

0

si può iniziare la discussione come:

ThreadPool.QueueUserWorkItem(DoStuff, input) 

e sarà interrompere automaticamente con l'applicazione stretta.