Compartilhar via


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.

Confira também