Condividi tramite


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 codice di terze parti non progettato per l'annullamento cooperativo. Nelle app .NET Framework è possibile usare il Thread.Abort metodo per terminare forzatamente un thread gestito. Quando si chiama Abort, Common Language Runtime genera un'eccezione ThreadAbortException nel thread di destinazione, che il thread di destinazione può intercettare. Tuttavia, il runtime di .NET Framework si occupa sempre automaticamente di rilanciare l'eccezione dopo il catch blocco. Per ulteriori informazioni, vedere Thread.Abort.

Il Thread.Abort metodo genera un'eccezione PlatformNotSupportedException in fase di esecuzione in .NET Core e .NET 5 e versioni successive. A partire da .NET 5, viene contrassegnato anche come obsoleto (SYSLIB0006), quindi la chiamata genera un avviso in fase di compilazione. Se è necessario terminare l'esecuzione di codice di terze parti forzatamente nelle implementazioni .NET moderne, eseguirlo nel processo separato e usare Process.Kill.

Annotazioni

  • Quando si chiama Thread.Abort per terminare un thread diverso da quello corrente, non si sa quale codice è stato eseguito o non eseguito correttamente quando viene generato ThreadAbortException. Non puoi essere certo dello stato della tua applicazione o di qualsiasi applicazione e stato dell'utente di cui è 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 relativo Abort metodo, il runtime lo contrassegna ThreadState.AbortRequested. L'eccezione viene generata quando il thread torna al codice gestito.

Una volta interrotto un thread, non può essere riavviato.

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

I thread in attesa di una chiamata al Thread.Join metodo 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 Abort dal proprio codice o 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 qualsiasi elaborazione finale in una finally clausola, 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 trovarsi nella catch clausola o nella finally clausola , perché un ThreadAbortException oggetto viene nuovamente generato dal sistema alla fine della finally clausola o alla fine della catch clausola se non è presente alcuna finally clausola.

È possibile impedire al sistema di generare nuovamente l'eccezione chiamando il Thread.ResetAbort metodo . Tuttavia, dovresti eseguire questa operazione solo se il tuo proprio codice ha causato il ThreadAbortException.

Vedere anche