Eliminare definitivamente thread

Per terminare l'esecuzione del thread, in genere si usa il modello di annullamento cooperativo. Tuttavia, a volte non è possibile arrestare un thread in modo cooperativo perché esegue un codice di terze parti non progettato per l'annullamento cooperativo. Nelle app .NET Framework è possibile usare il metodo Thread.Abort per terminare forzatamente un thread gestito. Quando si chiama Abort, Common Language Runtime genera un'eccezione ThreadAbortException nel thread di destinazione, che può essere rilevata dal thread di destinazione. Tuttavia, il runtime di .NET Framework genera sempre automaticamente l'eccezione dopo il blocco catch. Per altre informazioni, vedere Thread.Abort.

Il Thread.Abort metodo non è supportato in .NET 5 (incluso .NET Core) e versioni successive. Se è necessario terminare l'esecuzione di un codice di terze parti forzatamente in .NET 5+, è possibile eseguirlo nel processo separato e usare Process.Kill.

Nota

  • Quando si chiama Thread.Abort per interrompere un thread diverso dal thread corrente, non si sa quale codice è stato eseguito o non è riuscito a eseguire quando viene generato ThreadAbortException. Non è inoltre possibile essere certi dello stato dell'applicazione o di qualsiasi applicazione e stato utente responsabile del mantenimento. Ad esempio, la chiamata Thread.Abort può impedire l'esecuzione di costruttori statici o il rilascio di risorse gestite o non gestite.
  • Se un thread esegue codice non gestito quando viene chiamato il metodo Abort, il runtime lo contrassegna come ThreadState.AbortRequested. L'eccezione viene generata quando il thread torna al codice gestito.

Quando un thread viene interrotto, non può essere riavviato.

Il metodo Abort non determina l'interruzione immediata del thread perché il thread di destinazione può rilevare ThreadAbortException ed eseguire quantità arbitrarie di codice in un blocco finally. È possibile chiamare Thread.Join se è necessario attendere il completamento del thread. Thread.Join è una chiamata di blocco che non termina finché il thread non ha effettivamente arrestato l'esecuzione o è trascorso un intervallo di timeout facoltativo. Il thread interrotto può chiamare il metodo ResetAbort o eseguire un'elaborazione senza vincoli in un blocco finally, quindi, se non si specifica un timeout, non è sicuro che l'attesa termini.

I thread in attesa di una chiamata al metodo Thread.Join possono essere interrotti da altri thread che chiamano Thread.Interrupt.

Gestione di ThreadAbortException

Se si prevede che il thread venga interrotto, in seguito alla chiamata ad Abort dal codice o in seguito allo scaricamento di un dominio applicazione in cui il thread è in esecuzione (AppDomain.Unload usa Thread.Abort per terminare i thread), il thread deve gestire ThreadAbortException ed eseguire un'eventuale elaborazione finale in una clausola finally, come illustrato nel codice seguente.

Try  
    ' Code that is executing when the thread is aborted.  
Catch ex As ThreadAbortException  
    ' Clean-up code can go here.  
    ' If there is no Finally clause, ThreadAbortException is  
    ' re-thrown by the system at the end of the Catch clause.
Finally  
    ' Clean-up code can go here.  
End Try  
' Do not put clean-up code here, because the exception
' is rethrown at the end of the Finally clause.  
try
{  
    // Code that is executing when the thread is aborted.  
}
catch (ThreadAbortException ex)
{  
    // Clean-up code can go here.  
    // If there is no Finally clause, ThreadAbortException is  
    // re-thrown by the system at the end of the Catch clause.
}  
// Do not put clean-up code here, because the exception
// is rethrown at the end of the Finally clause.  

Il codice di pulizia deve essere nella clausola catch o nella clausola finally, perché un'eccezione ThreadAbortException viene nuovamente generata dal sistema alla fine della clausola finally o alla fine della clausola catch se non sono presenti clausole finally.

È possibile impedire che il sistema generi nuovamente l'eccezione chiamando il metodo Thread.ResetAbort. È tuttavia consigliabile farlo solo se il codice ha generato ThreadAbortException.

Vedi anche