Compartir a través de


MDA de asynchronousThreadAbort

Nota:

Este artículo es específico de .NET Framework. No se aplica a implementaciones más recientes de .NET, incluidas .NET 6 y versiones posteriores.

El Asistente para la depuración administrada (MDA) asynchronousThreadAbort se activa cuando un subproceso intenta incorporar una anulación asincrónica a otro subproceso. Las anulaciones de subproceso sincrónicas no activan el MDA asynchronousThreadAbort.

Síntomas

Una aplicación se bloquea con una ThreadAbortException no controlada cuando se anula el subproceso de aplicación principal. Si la aplicación siguiera ejecutándose, las consecuencias podrían ser peores que el bloqueo, posiblemente más datos dañados.

Las operaciones que debían ser atómicas es probable que se hayan interrumpido tras la finalización parcial, dejando los datos de la aplicación en un estado impredecible. Una ThreadAbortException se puede generar desde puntos aparentemente aleatorios de la ejecución de código, a menudo en ubicaciones desde las que no se esperaba que se generara una excepción. El código podría no ser capaz de controlar este tipo de excepción, lo que daría lugar a un estado dañado.

Los síntomas pueden variar enormemente debido a la aleatoriedad inherente al problema.

Causa

El código de un subproceso ha llamado al método Thread.Abort de un subproceso de destino para incorporar una anulación de subproceso asincrónica. La anulación de subproceso es asincrónica porque el código que realiza la llamada a Abort se ejecuta en un subproceso distinto al destino de la operación de anulación. Las anulaciones de subproceso sincrónicas no deberían causar problemas, ya que el subproceso que realiza la Abort debe haberla hecho únicamente en un punto de control seguro donde el estado de la aplicación es coherente.

Las anulaciones de subproceso asincrónicas presentan un problema, ya que se procesan en puntos impredecibles de la ejecución del subproceso de destino. Para evitar esto, el código escrito para ejecutarse en un subproceso que se pueda anular de este modo tendría que controlar una ThreadAbortException prácticamente en cada línea de código, teniendo cuidado de volver a poner los datos de la aplicación en un estado coherente. No es realista esperar que el código se escriba teniendo en cuenta este problema ni escribir código protegido frente a todas las circunstancias posibles.

Las llamadas a código no administrado y bloques finally no se anulan asincrónicamente, sino inmediatamente al salir de una de estas categorías.

La causa puede ser difícil de determinar debido a la aleatoriedad inherente al problema.

Solución

Evite el diseño de código que necesite anulaciones de subproceso asincrónicas. Existen varios enfoques más adecuados para la interrupción de un subproceso de destino que no requieren una llamada a Abort. El más seguro consiste en incorporar un mecanismo, como una propiedad común, que indique al subproceso de destino que solicite una interrupción. El subproceso de destino comprueba la señal en determinados puntos de control seguros. Si observa que se ha solicitado una interrupción, puede cerrar correctamente.

Efecto en el Runtime

Este MDA no tiene ningún efecto en el CLR. Solo notifica datos sobre las anulaciones de subproceso asincrónicas.

Output

El MDA notifica el identificador del subproceso que realiza la anulación y el identificador del subproceso que es el destino de ella. Nunca serán iguales, porque eso está limitado a las interrupciones asincrónicas.

Configuración

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

Ejemplo

La activación del MDA asynchronousThreadAbort solo exige una llamada a Abort en un subproceso independiente en ejecución. Tenga en cuenta las consecuencias si el contenido de la función de inicio del subproceso fuera un conjunto de operaciones más complejas que la anulación pudiera interrumpir en cualquier punto arbitrario.

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();
}

Consulte también