Leer en inglés

Compartir a través de


AppDomain.FirstChanceException Evento

Definición

Ocurre cuando se produce una excepción en código administrado, antes de que el runtime busque un controlador de excepciones en la pila de llamadas del dominio de aplicación.

C#
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>? FirstChanceException;
C#
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;
C#
[add: System.Security.SecurityCritical]
[remove: System.Security.SecurityCritical]
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;

Tipo de evento

Atributos

Ejemplos

En el ejemplo siguiente se crea una serie de dominios de aplicación denominados AD0 a través AD3de , con un Worker objeto en cada dominio de aplicación. Cada Worker objeto tiene una referencia al Worker objeto en el siguiente dominio de aplicación, excepto en el del Worker último dominio de aplicación. El FirstChanceException evento se controla en todos los dominios de aplicación, excepto AD1.

Nota

Además de este ejemplo, que muestra las notificaciones de excepción de primera oportunidad en varios dominios de aplicación, puede encontrar casos de uso simples en Cómo: Recibir notificaciones de excepción de First-Chance.

Cuando se han creado los dominios de aplicación, el dominio de aplicación predeterminado llama al TestException método para el primer dominio de aplicación. Cada Worker objeto llama al TestException método para el siguiente dominio de aplicación, hasta que la última Worker inicia una excepción que se controla o no se controla. Por lo tanto, el subproceso actual pasa por todos los dominios de aplicación y TestException se agrega a la pila en cada dominio de aplicación.

Cuando el último Worker objeto controla la excepción, el FirstChanceException evento solo se genera en el último dominio de aplicación. Los demás dominios de aplicación nunca tienen la oportunidad de controlar la excepción, por lo que el evento no se genera.

Cuando el último Worker objeto no controla la excepción, el FirstChanceException evento se genera en cada dominio de aplicación que tiene un controlador de eventos. Una vez finalizado cada controlador de eventos, la pila continúa desenredada hasta que el dominio de aplicación predeterminado detecta la excepción.

Nota

Para ver cómo crece la presentación de la pila a medida que el evento se acerca y se acerca al dominio de aplicación predeterminado, cambie e.Exception.Message a e.Exception en los FirstChanceHandler controladores de eventos. Tenga en cuenta que, cuando TestException se llama a través de los límites del dominio de aplicación, aparece dos veces: una para el proxy y una vez para el código auxiliar.

C#
using System;
using System.Reflection;
using System.Runtime.ExceptionServices;

class FirstChanceExceptionSnippet
{
    static void Main()
    {
        AppDomain.CurrentDomain.FirstChanceException += FirstChanceHandler;

        // Create a set of application domains, with a Worker object in each one.
        // Each Worker object creates the next application domain.
        AppDomain ad = AppDomain.CreateDomain("AD0");
        Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                                typeof(Worker).Assembly.FullName, "Worker");
        w.Initialize(0, 3);

        Console.WriteLine("\r\nThe last application domain throws an exception and catches it:");
        Console.WriteLine();
        w.TestException(true);

        try
        {
            Console.WriteLine(
                "\r\nThe last application domain throws an exception and does not catch it:");
            Console.WriteLine();
            w.TestException(false);
        }
        catch (ArgumentException ex)
        {
            Console.WriteLine("ArgumentException caught in {0}: {1}",
                AppDomain.CurrentDomain.FriendlyName, ex.Message);
        }
    }

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
}

public class Worker : MarshalByRefObject
{
    private AppDomain ad = null;
    private Worker w = null;

    public void Initialize(int count, int max)
    {
        // Handle the FirstChanceException event in all application domains except
        // AD1.
        if (count != 1)
        {
            AppDomain.CurrentDomain.FirstChanceException += FirstChanceHandler;
        }

        // Create another application domain, until the maximum is reached.
        // Field w remains null in the last application domain, as a signal
        // to TestException().
        if (count < max)
        {
            int next = count + 1;
            ad = AppDomain.CreateDomain("AD" + next);
            w = (Worker) ad.CreateInstanceAndUnwrap(
                             typeof(Worker).Assembly.FullName, "Worker");
            w.Initialize(next, max);
        }
    }

    public void TestException(bool handled)
    {
        // As long as there is another application domain, call TestException() on
        // its Worker object. When the last application domain is reached, throw a
        // handled or unhandled exception.
        if (w != null)
        {
            w.TestException(handled);
        }
        else if (handled)
        {
            try
            {
                throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
            }
            catch (ArgumentException ex)
            {
                Console.WriteLine("ArgumentException caught in {0}: {1}",
                    AppDomain.CurrentDomain.FriendlyName, ex.Message);
            }
        }
        else
        {
            throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
        }
    }

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
}

/* This example produces output similar to the following:

The last application domain throws an exception and catches it:

FirstChanceException event raised in AD3: Thrown in AD3
ArgumentException caught in AD3: Thrown in AD3

The last application domain throws an exception and does not catch it:

FirstChanceException event raised in AD3: Thrown in AD3
FirstChanceException event raised in AD2: Thrown in AD3
FirstChanceException event raised in AD0: Thrown in AD3
FirstChanceException event raised in Example.exe: Thrown in AD3
ArgumentException caught in Example.exe: Thrown in AD3
 */

Comentarios

Este evento es solo una notificación. Controlar este evento no controla la excepción ni afecta al control de excepciones posterior de ninguna manera. Una vez que se ha generado el evento y se han invocado controladores de eventos, Common Language Runtime (CLR) comienza a buscar un controlador para la excepción. FirstChanceException proporciona al dominio de aplicación una primera oportunidad de examinar cualquier excepción administrada.

El evento se puede controlar por dominio de aplicación. Si un subproceso pasa a través de varios dominios de aplicación mientras se ejecuta una llamada, el evento se genera en cada dominio de aplicación que ha registrado un controlador de eventos, antes de que CLR empiece a buscar un controlador de excepciones coincidente en ese dominio de aplicación. Una vez controlado el evento, se realiza una búsqueda para un controlador de excepciones coincidente en ese dominio de aplicación. Si no se encuentra ninguno, el evento se genera en el siguiente dominio de aplicación.

Debe controlar todas las excepciones que se producen en el controlador de eventos para el FirstChanceException evento. De lo contrario, FirstChanceException se genera de forma recursiva. Esto podría dar lugar a un desbordamiento de pila y a la finalización de la aplicación. Se recomienda implementar controladores de eventos para este evento como regiones de ejecución restringidas (CER), para mantener las excepciones relacionadas con la infraestructura, como el desbordamiento de memoria insuficiente o el desbordamiento de pila, que afecta a la máquina virtual mientras se procesa la notificación de excepción.

Este evento no se genera para excepciones que indican daños en el estado del proceso, como infracciones de acceso, a menos que el controlador de eventos sea crítico para la seguridad y tenga el HandleProcessCorruptedStateExceptionsAttribute atributo .

Common Language Runtime suspende las anulaciones de subprocesos mientras se controla este evento de notificación.

Se aplica a

Producto Versiones
.NET Core 2.0, Core 2.1, Core 2.2, Core 3.0, Core 3.1, 5, 6, 7, 8, 9, 10
.NET Framework 4.0, 4.5, 4.5.1, 4.5.2, 4.6, 4.6.1, 4.6.2, 4.7, 4.7.1, 4.7.2, 4.8, 4.8.1
.NET Standard 2.0, 2.1

Consulte también