Compartilhar via


Como: Receber notificações de exceção de primeira Chance

O FirstChanceException o evento da AppDomain classe permite que você recebe uma notificação de que uma exceção foi lançada, antes que o common language runtime começou a procurar por manipuladores de exceção.

O evento é disparado no nível do domínio do aplicativo. Uma thread de execução pode passar através de múltiplo domínios de aplicativo, portanto, uma exceção que não é tratada em um domínio do aplicativo pode ser tratada em outro domínio do aplicativo. A notificação ocorre em cada domínio do aplicativo que tenha adicionado um manipulador de Evento, até que um domínio do aplicativo lide com a exceção.

Os procedimentos e os exemplos neste artigo mostram como receber notificações de exceção de primeira chance em um programa simples que tem um domínio do aplicativo e em um domínio do aplicativo que você criar.

Para obter um exemplo mais complexo que se estende por vários domínios de aplicativo, consulte o exemplo para o FirstChanceException de evento.

Recebendo notificações de exceção de primeira Chance no domínio de aplicativo padrão

No procedimento a seguir, o ponto de entrada para o aplicativo, o Main() método, é executada no domínio de aplicativo padrão.

Para demonstrar as notificações de exceção de primeira chance no domínio de aplicativo padrão

  1. Definir um manipulador de eventos para o FirstChanceException evento, usando um lambda funcionam e anexá-lo ao evento. Neste exemplo, o manipulador de eventos imprime o nome do domínio do aplicativo onde o evento foi tratado e a exceção Message propriedade.

    Imports System.Runtime.ExceptionServices
    
    Class Example
    
        Shared Sub Main()
    
            AddHandler AppDomain.CurrentDomain.FirstChanceException, 
                       Sub(source As Object, e As FirstChanceExceptionEventArgs)
                           Console.WriteLine("FirstChanceException event raised in {0}: {1}",
                                             AppDomain.CurrentDomain.FriendlyName, 
                                             e.Exception.Message)
                       End Sub
    
    using System;
    using System.Runtime.ExceptionServices;
    
    class Example
    {
        static void Main()
        {
            AppDomain.CurrentDomain.FirstChanceException += 
                (object source, FirstChanceExceptionEventArgs e) =>
                {
                    Console.WriteLine("FirstChanceException event raised in {0}: {1}",
                        AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
                };
    
  2. Lance uma exceção e capture-a. Antes do runtime localiza o manipulador de exceção, o FirstChanceException evento é gerado e exibe uma mensagem. Esta mensagem é seguida pela mensagem que é exibida pelo manipulador de exceção.

    Try
        Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
    
    Catch ex As ArgumentException
    
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message)
    End Try
    
    try
    {
        throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message);
    }
    
  3. Lance uma exceção, mas não capture-a. Antes do runtime procura por um manipulador de exceção, o FirstChanceException evento é gerado e exibe uma mensagem. Como não há nenhum manipulador de exceção, então o aplicativo termina.

            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
        End Sub
    End Class
    
            throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
        }
    }
    

    O código que é mostrado nas três primeiras etapas desse procedimento forma um aplicativo de console completo. A saída do aplicativo varia, dependendo do nome do arquivo. exe, porque o nome do domínio de aplicativo padrão consiste no nome e extensão do arquivo. exe. Consulte o seguinte exemplo de saída.

    ' This example produces output similar to the following:
    '
    'FirstChanceException event raised in Example.exe: Thrown in Example.exe
    'ArgumentException caught in Example.exe: Thrown in Example.exe
    'FirstChanceException event raised in Example.exe: Thrown in Example.exe
    '
    'Unhandled Exception: System.ArgumentException: Thrown in Example.exe
    '   at Example.Main()
    
    /* This example produces output similar to the following:
    
    FirstChanceException event raised in Example.exe: Thrown in Example.exe
    ArgumentException caught in Example.exe: Thrown in Example.exe
    FirstChanceException event raised in Example.exe: Thrown in Example.exe
    
    Unhandled Exception: System.ArgumentException: Thrown in Example.exe
       at Example.Main()
     */
    

Recebendo notificações de exceção de primeira Chance em outro domínio de aplicativo

Se seu programa contiver mais que um domínio do aplicativo, você pode escolher quais domínios de aplicativo recebem notificações.

Para receber notificações de exceção de primeira chance em um domínio de aplicativo que você cria.

  1. Definir um manipulador de eventos para o FirstChanceException de evento. Este exemplo usa um static método (Shared método em Visual Basic) que imprime o nome do domínio do aplicativo onde o evento foi tratado e a exceção Message propriedade.

    Shared Sub FirstChanceHandler(ByVal source As Object, 
                                  ByVal e As FirstChanceExceptionEventArgs)
    
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message)
    End Sub
    
    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
    
  2. Criar um domínio de aplicativo e adicione o manipulador de eventos para o FirstChanceException o evento para esse domínio de aplicativo. Neste exemplo, o domínio de aplicativo é denominado AD1.

    Dim ad As AppDomain = AppDomain.CreateDomain("AD1")
    AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler
    
    AppDomain ad = AppDomain.CreateDomain("AD1");
    ad.FirstChanceException += FirstChanceHandler;
    

    Você pode tratar esse evento no domínio do aplicativo padrão da mesma maneira. Use o static (Shared em Visual Basic) AppDomain.CurrentDomain propriedade no Main() para obter uma referência para o domínio de aplicativo padrão.

Para demonstrar as notificações de exceção de primeira chance no domínio do aplicativo

  1. Criar um Worker o objeto no domínio do aplicativo que você criou no procedimento anterior. O Worker classe deve ser pública e deve derivar de MarshalByRefObject, conforme mostrado no exemplo concluído no final deste artigo.

    Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                Assembly.GetExecutingAssembly().FullName, "Worker"),
                            Worker)
    
    Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                            Assembly.GetExecutingAssembly().FullName, "Worker");
    
  2. Chamar um método do Worker objeto que lança uma exceção. Neste exemplo, o Thrower método é chamado duas vezes. Na primeira vez, o argumento de método é true, que faz com que o método para capturar sua própria exceção. Na segunda vez, o argumento é falsee o Main() método captura a exceção no domínio de aplicativo padrão.

    ' The worker throws an exception and catches it.
    w.Thrower(true)
    
    Try
        ' The worker throws an exception and doesn't catch it.
        w.Thrower(false)
    
    Catch ex As ArgumentException
    
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message)
    End Try
    
    // The worker throws an exception and catches it.
    w.Thrower(true);
    
    try
    {
        // The worker throws an exception and doesn't catch it.
        w.Thrower(false);
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine("ArgumentException caught in {0}: {1}", 
            AppDomain.CurrentDomain.FriendlyName, ex.Message);
    }
    
  3. Coloque o código de Thrower método para controlar se o método manipular sua própria exceção.

    If catchException
    
        Try
            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
    
        Catch ex As ArgumentException
    
            Console.WriteLine("ArgumentException caught in {0}: {1}", 
                AppDomain.CurrentDomain.FriendlyName, ex.Message)
        End Try
    Else
    
        Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
    End If
    
    if (catchException)
    {
        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);
    }
    

Exemplo

O exemplo a seguir cria um domínio de aplicativo chamado AD1 e adiciona um manipulador de eventos para o domínio de aplicativo FirstChanceException de evento. O exemplo cria uma instância da Worker de classe no domínio de aplicativo e chamadas para um método chamado Thrower que lança um ArgumentException. Dependendo do valor do argumento, o método captura a exceção ou falha ao lidar com ele.

Cada vez que o Thrower método lança uma exceção em AD1, o FirstChanceException evento é gerado no AD1, e o manipulador de eventos exibe uma mensagem. O ambiente de execução, em seguida, procura um manipulador de exceção. No primeiro caso, o manipulador de exceção é encontrado em AD1. No segundo caso, a exceção é sem tratamento em AD1e for pego no domínio de aplicativo padrão.

Observação

O nome do domínio de aplicativo padrão é o mesmo que o nome do executável.

Se você adicionar um manipulador para o FirstChanceException evento para o domínio de aplicativo padrão, o evento é gerado e tratado antes que o domínio de aplicativo padrão manipula a exceção. Para ver isso, adicione o código do C# AppDomain.CurrentDomain.FirstChanceException += FirstChanceException; (em Visual Basic, AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException) no início da Main().

Imports System.Reflection
Imports System.Runtime.ExceptionServices

Class Example

    Shared Sub Main()

        ' To receive first chance notifications of exceptions in 
        ' an application domain, handle the FirstChanceException
        ' event in that application domain.
        Dim ad As AppDomain = AppDomain.CreateDomain("AD1")
        AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler


        ' Create a worker object in the application domain.
        Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                    Assembly.GetExecutingAssembly().FullName, "Worker"),
                                Worker)

        ' The worker throws an exception and catches it.
        w.Thrower(true)

        Try
            ' The worker throws an exception and doesn't catch it.
            w.Thrower(false)

        Catch ex As ArgumentException

            Console.WriteLine("ArgumentException caught in {0}: {1}", 
                AppDomain.CurrentDomain.FriendlyName, ex.Message)
        End Try
    End Sub

    Shared Sub FirstChanceHandler(ByVal source As Object, 
                                  ByVal e As FirstChanceExceptionEventArgs)

        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message)
    End Sub
End Class

Public Class Worker
    Inherits MarshalByRefObject

    Public Sub Thrower(ByVal catchException As Boolean)

        If catchException

            Try
                Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)

            Catch ex As ArgumentException

                Console.WriteLine("ArgumentException caught in {0}: {1}", 
                    AppDomain.CurrentDomain.FriendlyName, ex.Message)
            End Try
        Else

            Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName)
        End If
    End Sub
End Class

' This example produces output similar to the following:
'
'FirstChanceException event raised in AD1: Thrown in AD1
'ArgumentException caught in AD1: Thrown in AD1
'FirstChanceException event raised in AD1: Thrown in AD1
'ArgumentException caught in Example.exe: Thrown in AD1
using System;
using System.Reflection;
using System.Runtime.ExceptionServices;

class Example
{
    static void Main()
    {
        // To receive first chance notifications of exceptions in 
        // an application domain, handle the FirstChanceException
        // event in that application domain.
        AppDomain ad = AppDomain.CreateDomain("AD1");
        ad.FirstChanceException += FirstChanceHandler;

        // Create a worker object in the application domain.
        Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                                Assembly.GetExecutingAssembly().FullName, "Worker");

        // The worker throws an exception and catches it.
        w.Thrower(true);

        try
        {
            // The worker throws an exception and doesn't catch it.
            w.Thrower(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
{
    public void Thrower(bool catchException)
    {
        if (catchException)
        {
            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);
        }
    }
}

/* This example produces output similar to the following:

FirstChanceException event raised in AD1: Thrown in AD1
ArgumentException caught in AD1: Thrown in AD1
FirstChanceException event raised in AD1: Thrown in AD1
ArgumentException caught in Example.exe: Thrown in AD1
 */

Compilando o código

  • Este exemplo é um aplicativo de linha de comando. Para compilar e executar esse código em Visual Studio 2010, adicione o código de C# Console.ReadLine(); (em Visual Basic, Console.ReadLine()) no final da Main(), para impedir que a janela de comando de fechar antes de ler a saída.

Consulte também

Referência

FirstChanceException