Share via


MDA asynchronousThreadAbort

O MDA (assistente para depuração gerenciada) asynchronousThreadAbort é ativado quando um thread tenta introduzir uma anulação assíncrona em outro thread. Anulações de thread síncronas não ativam o MDA asynchronousThreadAbort.

Sintomas

Um aplicativo falha com uma ThreadAbortException sem tratamento quando o thread do aplicativo principal é anulado. Se o aplicativo precisar continuar sendo executado, as consequências poderão ser piores do que uma falha do aplicativo, possivelmente resultando em mais dados corrompidos.

As operações que devem ser atômicas provavelmente foram interrompidas após a conclusão parcial, deixando os dados do aplicativo em um estado imprevisível. Uma ThreadAbortException pode ser gerada com base em pontos aparentemente aleatórios na execução do código, geralmente em locais dos quais uma exceção não deve surgir. O código pode não ter a capacidade de manipular uma exceção como essa, resultando em um estado corrompido.

Os sintomas podem variar muito devido à aleatoriedade inerente ao problema.

Causa

O código em um thread chamou o método Thread.Abort em um thread de destino para introduzir uma anulação de thread assíncrona. A anulação de thread é assíncrona porque o código que faz a chamada a Abort está em execução em um thread diferente do que o destino da operação de anulação. As anulações de thread síncronas não devem causar um problema porque o thread que executa a Abort deveria ter feito isso somente em um ponto de verificação seguro em que o estado do aplicativo é consistente.

Anulações de thread assíncrono apresentam um problema porque são processadas em pontos imprevisíveis na execução do thread de destino. Para evitar isso, o código escrito para ser executado em um thread que pode ser anulado dessa maneira precisará manipular uma ThreadAbortException em quase todas as linhas de código, tomando cuidado para colocar os dados do aplicativo novamente em um estado consistente. Não é realista esperar que o código seja escrito com esse problema em mente ou escrever um código que proteja contra todas as circunstâncias possíveis.

As chamadas no código não gerenciado e os blocos finally não serão anulados de forma assíncrona, mas imediatamente após a saída de uma dessas categorias.

A causa pode ser difícil de ser determinada devido à aleatoriedade inerente ao problema.

Resolução

Evite o design de código que exige o uso de anulações de thread assíncronas. Há várias abordagens mais apropriadas para a interrupção de um thread de destino que não exigem uma chamada a Abort. A mais segura é introduzir um mecanismo, como uma propriedade comum, que sinaliza o thread de destino a solicitar uma interrupção. O thread de destino verifica o sinal em determinados pontos de verificação seguros. Se ele observa que uma interrupção foi solicitada, ele pode ser desligado normalmente.

Efeito sobre o runtime

Esse MDA não tem efeito sobre o CLR. Ele apenas relata dados sobre as anulações de thread assíncronas.

Saída

O MDA relata a ID do thread que executa a anulação e a ID do thread que é o destino da anulação. Elas nunca serão as mesmas porque isso é limitado a anulações assíncronas.

Configuração

<mdaConfig>
  <assistants>
    <asynchronousThreadAbort />
  </assistants>
</mdaConfig>

Exemplo

A ativação do MDA asynchronousThreadAbort exige apenas uma chamada a Abort em um thread de execução separado. Considere as consequências se o conteúdo da função de início do thread fosse um conjunto de operações mais complexas que poderiam ser interrompidas em qualquer ponto arbitrário pela anulação.

using System.Threading;
void FireMda()
{
    Thread t = new Thread(delegate() { Thread.Sleep(1000); });
    t.Start();
    // The following line activates the MDA.
    t.Abort();
    t.Join();
}

Confira também