Sdílet prostřednictvím


Postupy: Přijímání oznámení o první odpovídající výjimce

Poznámka:

Tento článek je specifický pro rozhraní .NET Framework. Nevztahuje se na novější implementace .NET, včetně .NET 6 a novějších verzí.

Událost FirstChanceExceptionAppDomain třídy umožňuje obdržet oznámení, že došlo k výjimce dříve, než modul CLR (Common Language Runtime) začal hledat obslužné rutiny výjimek.

Událost se vyvolá na úrovni domény aplikace. Vlákno provádění může procházet více domén aplikace, takže výjimku, která je neošetřená v jedné doméně aplikace, by mohla být zpracována v jiné doméně aplikace. K oznámení dochází v každé doméně aplikace, která přidala obslužnou rutinu události, dokud doména aplikace nezpracuje výjimku.

Postupy a příklady v tomto článku ukazují, jak přijímat oznámení o výjimce první šance v jednoduchém programu, který má jednu doménu aplikace a v doméně aplikace, kterou vytvoříte.

Složitější příklad, který zahrnuje několik domén aplikace, najdete v příkladu FirstChanceException události.

Příjem oznámení o výjimce první šance ve výchozí doméně aplikace

V následujícím postupu se vstupní bod aplikace, Main() metoda, spouští ve výchozí doméně aplikace.

Předvedení oznámení o výjimce první šance ve výchozí doméně aplikace

  1. Definujte obslužnou rutinu FirstChanceException události pro událost pomocí funkce lambda a připojte ji k události. V tomto příkladu obslužná rutina události vytiskne název domény aplikace, kde byla událost zpracována, a vlastnost výjimky 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. Vyvolá výjimku a zachytí ji. Než modul runtime vyhledá obslužnou rutinu výjimky, FirstChanceException vyvolá se událost a zobrazí zprávu. Za touto zprávou následuje zpráva zobrazená obslužnou rutinou výjimky.

    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. Vyvolá výjimku, ale nezachyťte ji. Než modul runtime vyhledá obslužnou rutinu výjimky, FirstChanceException vyvolá se událost a zobrazí zprávu. Neexistuje žádná obslužná rutina výjimky, takže aplikace se ukončí.

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

    Kód zobrazený v prvních třech krocích tohoto postupu tvoří úplnou konzolovou aplikaci. Výstup aplikace se liší v závislosti na názvu souboru .exe, protože název výchozí domény aplikace se skládá z názvu a přípony souboru .exe. Ukázkový výstup najdete v následujícím příkladu.

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

Příjem oznámení o výjimce první šance v jiné doméně aplikace

Pokud váš program obsahuje více než jednu doménu aplikace, můžete zvolit, které domény aplikace přijímají oznámení.

Příjem oznámení o výjimce první šance v doméně aplikace, kterou vytvoříte

  1. Definujte obslužnou rutinu FirstChanceException události pro událost. Tento příklad používá metodu static (Shared metodu v jazyce Visual Basic), která vytiskne název domény aplikace, kde byla událost zpracována, a vlastnost výjimky 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. Vytvořte doménu aplikace a přidejte obslužnou rutinu události do události pro danou FirstChanceException doménu aplikace. V tomto příkladu je doména aplikace pojmenována AD1.

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

    Tuto událost můžete zpracovat ve výchozí doméně aplikace stejným způsobem. static Pomocí vlastnosti Main() (Shared v jazyce Visual Basic) AppDomain.CurrentDomain získejte odkaz na výchozí doménu aplikace.

Předvedení oznámení o výjimce první šance v doméně aplikace

  1. Vytvořte Worker objekt v doméně aplikace, kterou jste vytvořili v předchozím postupu. Třída Worker musí být veřejná a musí být odvozena od MarshalByRefObject, jak je znázorněno v úplném příkladu na konci tohoto článku.

    Worker w = (Worker) ad.CreateInstanceAndUnwrap(
                            typeof(Worker).Assembly.FullName, "Worker");
    
    Dim w As Worker = CType(ad.CreateInstanceAndUnwrap(
                                GetType(Worker).Assembly.FullName, "Worker"),
                            Worker)
    
  2. Volání metody objektu Worker , který vyvolá výjimku. V tomto příkladu Thrower se metoda volá dvakrát. Argument metody je truepoprvé , což způsobí, že metoda zachytit vlastní výjimku. Druhý argument je falsea Main() metoda zachytí výjimku ve výchozí doméně aplikace.

    // 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. Umístěte do metody kód Thrower , který určuje, jestli metoda zpracovává vlastní výjimku.

    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
    

Příklad

Následující příklad vytvoří doménu aplikace s názvem AD1 a přidá obslužnou rutinu události do události domény FirstChanceException aplikace. Příklad vytvoří instanci Worker třídy v doméně aplikace a volá metodu s názvemThrower, která vyvolá .ArgumentException V závislosti na hodnotě argumentu metoda buď zachytí výjimku, nebo ji nezpracuje.

Pokaždé, Thrower když metoda vyvolá výjimku v AD1, FirstChanceException událost je vyvolána AD1v a obslužná rutina události zobrazí zprávu. Modul runtime pak vyhledá obslužnou rutinu výjimky. V prvním případě se obslužná rutina výjimky nachází v AD1souboru . V druhém případě je výjimka neošetřená AD1a místo toho je zachycena ve výchozí doméně aplikace.

Poznámka:

Název výchozí domény aplikace je stejný jako název spustitelného souboru.

Pokud přidáte obslužnou rutinu FirstChanceException události do výchozí domény aplikace, je událost vyvolána a zpracována před výchozí doménou aplikace zpracovává výjimku. Chcete-li to zobrazit, přidejte na začátek Main()kódu AppDomain.CurrentDomain.FirstChanceException += FirstChanceException; jazyka C# (v jazyce Visual BasicAddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException) .

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

Viz také