2009-08-25 14 views
41

Sto usando il metodo thread.Abort per terminare il thread, ma non funziona. C'è un altro modo per terminare il thread?Come uccidere un thread istantaneamente in C#?

private void button1_Click(object sender, EventArgs e) 
{ 
    if (Receiver.IsAlive == true) 
    { 
     MessageBox.Show("Alive"); 
     Receiver.Abort(); 
    } 
    else 
    { 
     MessageBox.Show("Dead"); 
     Receiver.Start(); 
    } 
} 

Sto usando questo, ma ogni volta che mi lo stato Alive, Receiver è il mio filo globale.

+10

Pericolo, Will Robinson, Pericolo! Essere ** molto ** timidi nell'usare Thread.Abort - quasi sempre una cattiva idea. –

+4

Quindi cosa dovrebbe essere usato per uccidere il thread? – Mobin

+3

Chiedere al thread di fermarsi e ignorare il thread da quel momento in poi. – MSalters

risposta

58

Il motivo per cui è difficile uccidere un thread è perché i progettisti di linguaggio desiderano evitare il seguente problema: il thread prende un blocco e quindi lo uccide prima che possa rilasciarlo. Ora chiunque abbia bisogno di quella serratura rimarrà bloccato.

Quello che devi fare è usare alcune variabili globali per dire al thread di fermarsi. Devi manualmente, nel tuo codice thread, controllare che la variabile globale e tornare se lo vedi indica che devi fermarti.

+0

Io uso questo meccanismo da solo. Per il codice basato su UI, imposto una variabile globale e per i servizi controllo una tabella di database. Bello e prevedibile. –

+5

Se possibile, utilizzare ManualResetEvent anziché una variabile, per cui sono progettati. –

+3

Sono curioso ora - come sarebbe il ManualResetEvent essere superiore, per verificare una condizione di risoluzione anticipata? Capisco che sono migliori quando dobbiamo bloccare qualcosa, ma qui non c'è alcun blocco. – redtuna

6

thread verrà ucciso quando ha finito è lavoro, quindi se si sta utilizzando loop o qualcos'altro si dovrebbe passare variabile al thread per interrompere il ciclo dopo che il thread sarà finito.

4

C# Thread.Abort NON è garantito per interrompere istantaneamente il thread. Probabilmente funzionerà quando un thread chiama Abort su se stesso ma non quando un thread chiama su un altro.

Si prega di fare riferimento alla documentazione: http://msdn.microsoft.com/en-us/library/ty8d3wta.aspx

Ho affrontato questo problema strumenti che interagiscono con l'hardware di scrittura - si desidera arresto immediato, ma non è garantito. Di solito uso alcuni flag o altre logiche di questo tipo per impedire l'esecuzione di parti di codice in esecuzione su un thread (e che non voglio essere eseguito su abort-tricky).

14

Si dovrebbe prima avere un metodo concordato per terminare il thread. Ad esempio un running_valido che il thread può controllare e rispettare.

Il codice del thread principale deve essere racchiuso in un blocco di eccezioni che raccolga sia ThreadInterruptException che ThreadAbortException che puliranno in modo pulito il thread all'uscita.

Nel caso di ThreadInterruptException è possibile controllare la variabile running_ per vedere se è necessario continuare. Nel caso di ThreadAbortException, è necessario riordinare immediatamente e uscire dalla procedura di thread.

Il codice che cerca di fermare il filo dovrebbe effettuare le seguenti operazioni:

running_ = false; 
threadInstance_.Interrupt(); 
if(!threadInstance_.Join(2000)) { // or an agreed resonable time 
    threadInstance_.Abort(); 
} 
+2

Questa è l'unica risposta accettabile dal mio punto di vista. Sì, devi prima avere una variabile da notare quando il thread può uscire ma se stai bloccando il thread potresti non avere l'opportunità di controllare quella variabile. Ci deve essere un altro modo per interrompere un thread che è bloccato e questa risposta ha risolto il mio problema. Grazie! – CramerTV

+0

Se 'threadInstance_.Interrupt()' termina il thread velocemente, 'threadInstance_.Join' genererà * System.Threading.ThreadStateException: Thread non avviato * – Hannobo

24

Si può uccidere istantaneamente farlo in questo modo:

private Thread _myThread = new Thread(SomeThreadMethod); 

private void SomeThreadMethod() 
{ 
    // do whatever you want 
} 

[SecurityPermissionAttribute(SecurityAction.Demand, ControlThread = true)] 
private void KillTheThread() 
{ 
    _myThread.Abort(); 
} 

io uso sempre e funziona per me:)

+0

Ma vedi http://stackoverflow.com/a/1560567/199364 e altre risposte che descrivono perché thread.abort è rischioso. – ToolmakerSteve

+2

[La risposta di Adrian Regan] (http://stackoverflow.com/a/1327377/199364) è un modo MOLTO più sicuro di usare 'Abort' - come ultima risorsa se un thread non sta morendo. – ToolmakerSteve

-1
private void ResumeButton_Click(object sender, RoutedEventArgs e) 
    { 
     Task.Factory.StartNew(() => 
     { 
      Application.Current.Resources["AutoPilotThreadStatus"] = true; 
      Thread.CurrentThread.Name = "ResumeAutoPilot"; 
      Thread.CurrentThread.IsBackground = true; 
      AutoPilotHandler.ResumeAutoPilot(); 
     }); 
    } 

    public static void ResumeAutoPilot() 
    { 
     while ((bool)Application.Current.Resources["AutoPilotThreadStatus"]) 
     { 
      CheckAutoPilotThreadStatus(); 
      var searchYoutube = YoutubeHandler.Search("small truck"); 
      CheckAutoPilotThreadStatus(); 
      SaveVideosToDatabase(searchYoutube); 
      CheckAutoPilotThreadStatus(); 
     } 
    } 

    public static void CheckAutoPilotThreadStatus() 
    { 
     if (!(bool)Application.Current.Resources["AutoPilotThreadStatus"]) 
     { 
      KillCurrentThread(); 
     } 
    } 

    public static void KillCurrentThread() 
    { 
     Thread.CurrentThread.Abort(); 
    } 
+3

Un esempio perfetto di come le risorse dell'app non devono essere utilizzate. –

Problemi correlati