Como posso detectar um ThreadAbortException em um bloco finally? (.LÍQUIDO)

votos
8

Eu tenho alguma lógica crítica em um bloco finalmente (com um bloco try vazio), porque eu quero garantir que o código é executado mesmo que o fio é abortada. No entanto, eu também gostaria de detectar o ThreadAbortException. Descobri que envolver minha tentativa crítica / finally bloquear em um try / catch não pegar o ThreadAbortException. Existe alguma maneira de detectá-lo?

experimentar {
    experimentar { }
    finalmente {
        // lógica crítica
    }
} Catch (excepção ex) {
    // ThreadAbortException não é pego aqui, mas exceções jogado
    // de dentro da lógica crítica são
}
Publicado 09/12/2008 em 17:02
fonte usuário
Em outras línguas...                            


7 respostas

votos
2

Leia sobre Regiões de execução restrita .

Especificamente, o método RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup serão úteis aqui.

Respondeu 09/12/2008 em 17:04
fonte usuário

votos
3

Você pode realmente executar código na instrução catch muito bem para um ThreadAbortException. O problema é que a exceção será relançada uma vez execução deixa o bloco catch.

Se você quiser realmente parar a exceção de continuar você pode chamar Thread.ResetAbort (). Isto requer plena confiança embora e se você tiver um cenário específico, é quase certamente a coisa errada a fazer.

ThreadAbortException

Respondeu 09/12/2008 em 17:07
fonte usuário

votos
2

Eu não acho que é possível.

Por que você precisa para lidar com o ThreadAbortException em primeiro lugar? Chamando Thread.Abort () é geralmente um sinal de design ruim. Tem uma variável de sinalizador que, quando definido como true irá simplesmente retornar; a partir da função de fio, após limpeza apropriada de curso.

Dessa forma, você não vai precisar se preocupar com a exceção.

Respondeu 09/12/2008 em 17:22
fonte usuário

votos
0

Concordo com arul. Chamando Thread.Abort () é um sinal de design ruim.

Deixe-me citar Peter Ritchie da MSDN: Thread.Abort (a ênfase é minha):

Há muitas razões para não usar Thread.Abort e ThreadAbortException

Em certas plataformas (como x64 e IA64) a anulação pode ocorrer antes Monitor.Enter e um bloco try (mesmo com bloqueio / SyncLock), deixando o monitor órfão. A ThreadAbortException pode ocorrer no código do 3o partido não está escrito para lidar com abort segmento. O fio pode ser cancelada durante o processamento de um bloco finally no .NET 1.x usa exceções para a lógica de controle de fluxo normal. exceção assíncrona pode interromper modificação do estado caco ou recursos, deixando-os corrompido.

Para mais detalhes ver:
http://msmvps.com/blogs/peterritchie/archive/2007/08/22/thead-abort-is-a-sign-of-a-poorly-designed-program.aspx
http: // www.bluebytesoftware.com/blog/2007/01/30/MonitorEnterThreadAbortsAndOrphanedLocks.aspx
http://blogs.msdn.com/ericlippert/archive/2007/08/17/subtleties-of-c-il-codegen.aspx

Respondeu 11/12/2008 em 11:43
fonte usuário

votos
0

você já tentou algo parecido com isto?

try {
    try { }
    catch (ThreadAbortException)
    {
      ThreadAbortExceptionBool = true;
    }
    finally {
        // critical logic
        if (ThreadAbortExceptionBool)
          // Whatever
    }
} 
catch(Exception ex) {
    // ThreadAbortException is not caught here, but exceptions thrown
    // from within the critical logic are
}
Respondeu 02/03/2009 em 16:15
fonte usuário

votos
8

Este é um problema curioso.

O código que você postou deve trabalhar. Parece que há algum tipo de otimização acontecendo que decide não chamar seu manipulador catch.

Então, eu queria para detectar a exceção com o seguinte:

bool threadAborted = true;
try {
  try { }
  finally { /* critical code */ }
  threadAborted = false;
}
finally {
  Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");

(Meu código atual apenas dormia em que seção de código crítico, para que eu pudesse ter certeza de que iria abortar depois que finalmente.)

É impressa:

Tópico abortada? Falso

Hmmm, realmente estranho!

Então eu pensei em fazer um pouco mais de trabalho lá, para enganar qualquer otimizações "inteligentes":

bool threadAborted = true;
try {
  try { }
  finally { /* critical code */ }
  threadAborted = AmIEvil();
}
finally {
  Console.WriteLine("Thread aborted? {0}", threadAborted);
}
Console.WriteLine("Done");

Onde AmIEvilé apenas:

[MethodImpl(MethodImplOptions.NoInlining)]
static bool AmIEvil() {
  return false;
}

Finalmente, impressos:

Tópico abortada? Verdade

E aí está. Usar isso em seu código:

try {
  try { }
  finally { /* critical code */ }
  NoOp();
}
catch (Exception ex) {
  // ThreadAbortException is caught here now!
}

Onde NoOpé apenas:

[MethodImpl(MethodImplOptions.NoInlining)]
static void NoOp() { }
Respondeu 03/03/2011 em 19:02
fonte usuário

votos
2

Se chamar Thread.Abort é design ruim por que SQL Server chamá-lo em um segmento que está executando o código do usuário? Porque isso é exatamente como uma consulta cancelar é tratado e que provoca pesadelos.

Respondeu 18/11/2011 em 22:23
fonte usuário

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more