Porady: odbieranie powiadomień o wyjątkach pierwszej szansy

Zdarzenie FirstChanceExceptionAppDomain klasy umożliwia odbieranie powiadomienia, że zgłoszono wyjątek, zanim środowisko uruchomieniowe języka wspólnego rozpoczęło wyszukiwanie procedur obsługi wyjątków.

Zdarzenie jest wywoływane na poziomie domeny aplikacji. Wątek wykonywania może przechodzić przez wiele domen aplikacji, więc wyjątek, który nie jest obsługiwany w jednej domenie aplikacji, może być obsługiwany w innej domenie aplikacji. Powiadomienie odbywa się w każdej domenie aplikacji, która dodała procedurę obsługi dla zdarzenia, dopóki domena aplikacji nie obsłuży wyjątku.

Procedury i przykłady w tym artykule pokazują, jak otrzymywać powiadomienia o wyjątkach pierwszej szansy w prostym programie, który ma jedną domenę aplikacji i w utworzonej domenie aplikacji.

Aby zapoznać się z bardziej złożonym przykładem obejmującym kilka domen aplikacji, zobacz przykład zdarzenia FirstChanceException .

Otrzymywanie powiadomień o wyjątku pierwszej szansy w domyślnej domenie aplikacji

W poniższej procedurze punkt wejścia dla aplikacji, Main() metoda, jest uruchamiany w domyślnej domenie aplikacji.

Aby zademonstrować powiadomienia o wyjątkach pierwszej szansy w domyślnej domenie aplikacji

  1. Zdefiniuj program obsługi zdarzeń dla FirstChanceException zdarzenia przy użyciu funkcji lambda i dołącz go do zdarzenia. W tym przykładzie program obsługi zdarzeń wyświetla nazwę domeny aplikacji, w której obsłużono zdarzenie i właściwość wyjątku Message .

    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);
                };
    
    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
    
  2. Wyrzuć wyjątek i przechwyć go. Zanim środowisko uruchomieniowe zlokalizuj program obsługi wyjątków, FirstChanceException zostanie zgłoszone zdarzenie i wyświetli komunikat. Po tym komunikacie jest wyświetlany komunikat programu obsługi wyjątków.

    try
    {
        throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName);
    }
    catch (ArgumentException ex)
    {
        Console.WriteLine("ArgumentException caught in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, ex.Message);
    }
    
    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
    
  3. Wyrzuć wyjątek, ale go nie przechwyć. Zanim środowisko uruchomieniowe wyszukuje program obsługi wyjątków, FirstChanceException zdarzenie jest wywoływane i wyświetla komunikat. Nie ma procedury obsługi wyjątków, więc aplikacja kończy działanie.

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

    Kod przedstawiony w pierwszych trzech krokach tej procedury tworzy kompletną aplikację konsolową. Dane wyjściowe aplikacji różnią się w zależności od nazwy pliku .exe, ponieważ nazwa domyślnej domeny aplikacji składa się z nazwy i rozszerzenia pliku .exe. Zobacz następujące informacje, aby uzyskać przykładowe dane wyjściowe.

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

Otrzymywanie powiadomień o wyjątku pierwszej szansy w innej domenie aplikacji

Jeśli program zawiera więcej niż jedną domenę aplikacji, możesz wybrać, które domeny aplikacji odbierają powiadomienia.

Aby otrzymywać powiadomienia o wyjątkach pierwszej szansy w utworzonej domenie aplikacji

  1. Zdefiniuj program obsługi zdarzeń dla FirstChanceException zdarzenia. W tym przykładzie static użyto metody (Shared metody w Visual Basic), która wyświetla nazwę domeny aplikacji, w której obsłużono zdarzenie i właściwość wyjątku Message .

    static void FirstChanceHandler(object source, FirstChanceExceptionEventArgs e)
    {
        Console.WriteLine("FirstChanceException event raised in {0}: {1}",
            AppDomain.CurrentDomain.FriendlyName, e.Exception.Message);
    }
    
    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
    
  2. Utwórz domenę aplikacji i dodaj procedurę obsługi zdarzeń do FirstChanceException zdarzenia dla tej domeny aplikacji. W tym przykładzie domena aplikacji ma nazwę AD1.

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

    To zdarzenie można obsłużyć w domyślnej domenie aplikacji w taki sam sposób. static Użyj właściwości Main() (Shared w visual basic), AppDomain.CurrentDomain aby uzyskać odwołanie do domyślnej domeny aplikacji.

Aby zademonstrować powiadomienia o wyjątkach pierwszej szansy w domenie aplikacji

  1. Worker Utwórz obiekt w domenie aplikacji utworzonej w poprzedniej procedurze. Klasa musi być publiczna Worker i musi pochodzić z MarshalByRefObjectklasy , jak pokazano w pełnym przykładzie na końcu tego artykułu.

    Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                            typeof(Worker).Assembly.FullName, "Worker");
    
    Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                GetType(Worker).Assembly.FullName, "Worker"),
                            Worker)
    
  2. Wywołaj metodę Worker obiektu, która zgłasza wyjątek. W tym przykładzie metoda jest wywoływana Thrower dwukrotnie. Po raz pierwszy argument metody to true, co powoduje, że metoda przechwyci własny wyjątek. Po raz drugi argument to false, a Main() metoda przechwytuje wyjątek w domyślnej domenie aplikacji.

    // 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);
    }
    
    ' 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
    
  3. Umieść kod w metodzie, Thrower aby określić, czy metoda obsługuje własny wyjątek.

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

Przykład

Poniższy przykład tworzy domenę aplikacji o nazwie AD1 i dodaje procedurę obsługi zdarzeń do zdarzenia domeny FirstChanceException aplikacji. Przykład tworzy wystąpienie Worker klasy w domenie aplikacji i wywołuje metodę o nazwie Thrower , która zgłasza błąd ArgumentException. W zależności od wartości argumentu metoda przechwytuje wyjątek lub nie może go obsłużyć.

Za każdym razem, Thrower gdy metoda zgłasza wyjątek w AD1pliku , FirstChanceException zdarzenie jest zgłaszane w AD1elemecie , a program obsługi zdarzeń wyświetla komunikat. Następnie środowisko uruchomieniowe wyszukuje procedurę obsługi wyjątków. W pierwszym przypadku program obsługi wyjątków znajduje się w pliku AD1. W drugim przypadku wyjątek jest nieobsługiwany w AD1elemencie , a zamiast tego jest przechwycony w domyślnej domenie aplikacji.

Uwaga

Nazwa domyślnej domeny aplikacji jest taka sama jak nazwa pliku wykonywalnego.

Jeśli dodasz program obsługi zdarzenia FirstChanceException do domyślnej domeny aplikacji, zdarzenie zostanie zgłoszone i obsłużone, zanim domyślna domena aplikacji obsłuży wyjątek. Aby to zobaczyć, dodaj kod AppDomain.CurrentDomain.FirstChanceException += FirstChanceException; c# (w Visual Basic, AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException) na początku Main().

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(
                                typeof(Worker).Assembly.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
 */
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(
                                    GetType(Worker).Assembly.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

Zobacz też