Ler em inglês

Compartilhar via


AppDomain.FirstChanceException Evento

Definição

Ocorre quando uma exceção é lançada no código gerenciado, antes que o runtime procure na pilha de chamadas um manipulador de exceção no domínio do aplicativo.

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

Tipo de evento

Atributos

Exemplos

O exemplo a seguir cria uma série de domínios de aplicativo chamados AD0 por meio AD3de , com um Worker objeto em cada domínio do aplicativo. Cada Worker objeto tem uma referência ao Worker objeto no próximo domínio do aplicativo, exceto para o Worker no último domínio do aplicativo. O FirstChanceException evento é tratado em todos os domínios do aplicativo, exceto AD1.

Observação

Além deste exemplo, que demonstra notificações de exceção de primeira chance em vários domínios de aplicativo, você pode encontrar casos de uso simples em Como receber First-Chance notificações de exceção.

Quando os domínios do aplicativo foram criados, o domínio do aplicativo padrão chama o TestException método para o primeiro domínio do aplicativo. Cada Worker objeto chama o TestException método para o próximo domínio do aplicativo, até que o último Worker gere uma exceção que seja manipulada ou sem tratamento. Assim, o thread atual passa por todos os domínios do aplicativo e TestException é adicionado à pilha em cada domínio do aplicativo.

Quando o último Worker objeto manipula a exceção, o FirstChanceException evento é gerado somente no último domínio do aplicativo. Os outros domínios de aplicativo nunca têm a chance de lidar com a exceção, portanto, o evento não é gerado.

Quando o último Worker objeto não manipula a exceção, o FirstChanceException evento é gerado em cada domínio de aplicativo que tem um manipulador de eventos. Após a conclusão de cada manipulador de eventos, a pilha continuará desenrolando até que a exceção seja capturada pelo domínio do aplicativo padrão.

Observação

Para ver como a exibição de pilha cresce à medida que o evento é gerado cada vez mais perto do domínio de aplicativo padrão, altere e.Exception.Message para e.Exception nos FirstChanceHandler manipuladores de eventos. Observe que, quando TestException é chamado entre os limites do domínio do aplicativo, ele aparece duas vezes: uma para o proxy e uma para o stub.

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
 */

Comentários

Esse evento é apenas uma notificação. O tratamento desse evento não manipula a exceção nem afeta o tratamento de exceção subsequente de forma alguma. Depois que o evento for acionado e os manipuladores de eventos forem invocados, o CLR (Common Language Runtime) começará a pesquisar uma exceção em um manipulador. FirstChanceException fornece ao domínio do aplicativo uma primeira chance de examinar qualquer exceção gerenciada.

O evento pode ser tratado por domínio do aplicativo. Se um thread passar por vários domínios de aplicativo durante a execução de uma chamada, o evento será gerado em cada domínio de aplicativo que registrou um manipulador de eventos, antes que o CLR comece a procurar um manipulador de exceção correspondente nesse domínio de aplicativo. Depois que o evento for tratado, uma pesquisa será feita para um manipulador de exceção correspondente nesse domínio de aplicativo. Se nenhum for encontrado, o evento será gerado no próximo domínio do aplicativo.

Você deve lidar com todas as exceções que ocorrem no manipulador de eventos do FirstChanceException evento. Caso contrário, FirstChanceException será gerado recursivamente. Isso pode resultar em um estouro de pilha e terminação do aplicativo. Recomendamos que você implemente manipuladores de eventos para esse evento como CERs (regiões de execução restritas), para impedir que exceções relacionadas à infraestrutura, como falta de memória ou estouro de pilha, afetem a máquina virtual enquanto a notificação de exceção está sendo processada.

Esse evento não é gerado para exceções que indicam corrupção do estado do processo, como violações de acesso, a menos que o manipulador de eventos seja crítico à segurança e tenha o HandleProcessCorruptedStateExceptionsAttribute atributo .

O Common Language Runtime suspende as anulações de thread enquanto esse evento de notificação está sendo tratado.

Aplica-se a

Produto Versões
.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

Confira também