Destruir threads
Para encerrar a execução do thread, você geralmente usa o modelo de cancelamento cooperativo. No entanto, às vezes não é possível interromper um thread de modo cooperativo, pois ele executa código de terceiros não projetado para cancelamento cooperativo. Em aplicativos .NET Framework, você pode usar o método Thread.Abort para encerrar um thread gerenciado à força. Quando você chama Abort, o Common Language Runtime lança um ThreadAbortException no thread de destino, que o thread de destino pode capturar. (No entanto, o runtime do .NET Framework sempre gera novamente a exceção automaticamente após o bloco catch
.) Para obter mais informações, consulte Thread.Abort.
Não há suporte para o método Thread.Abort no .NET 5 (incluindo o .NET Core) e versões posteriores. Se você precisar encerrar a execução do código de terceiros à força no .NET 5+, execute-o no processo separado e use Process.Kill.
Observação
- Quando você chama Thread.Abort para anular um thread diferente do atual, não sabe qual código foi ou não executado quando o erro ThreadAbortException é gerado. Você também não tem certeza sobre o estado do seu aplicativo ou de qualquer outro, e estado do usuário que ele é responsável por preservar. Por exemplo, a chamada de Thread.Abort pode impedir a execução de construtores estáticos ou a liberação de recursos gerenciados ou não gerenciados.
- Se um thread estiver executando um código não gerenciado quando seu método Abort for chamado, o runtime o marca ThreadState.AbortRequested. A exceção é lançada quando o thread retorna para código gerenciado.
Após a anulação de um thread, ele não poderá ser reiniciado.
O método Abort não causa a anulação imediata do thread, porque o thread de destino pode capturar o ThreadAbortException e executar valores arbitrários de código em um bloco finally
. Você poderá chamar Thread.Join se precisar esperar até que o thread seja encerrado. Thread.Join é uma chamada de bloqueio que não retorna até que o thread realmente tenha parado de executar ou um intervalo de tempo limite opcional tenha transcorrido. O thread anulado poderia chamar o método ResetAbort ou executar o processamento não associado em um bloqueio finally
, então se você não especificar um tempo limite, não será garantido o término da espera.
Os threads que estão aguardando uma chamada para o método Thread.Join podem ser interrompidos por outros threads de chamam Thread.Interrupt.
Como lidar com a ThreadAbortException
Se você espera que o thread seja anulado, como resultado de uma chamada a Abort de seu próprio código, ou como resultado do descarregamento de um domínio de aplicativo no qual o thread está em execução (AppDomain.Unload usa Thread.Abort para encerrar os threads), o thread deverá tratar de ThreadAbortException e executar qualquer processamento final em uma cláusula finally
, conforme mostrado no código a seguir.
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.
Seu código de limpeza deve estar na cláusula catch
ou na cláusula finally
, porque uma ThreadAbortException é lançada novamente pelo sistema no final da cláusula finally
ou no final da cláusula catch
se não houver nenhuma cláusula finally
.
Você pode impedir que o sistema relance a exceção chamando o método Thread.ResetAbort. No entanto, você deve fazer isso apenas se seu próprio código tiver causado a ThreadAbortException.