AppDomain.FirstChanceException Ereignis

Definition

Tritt auf, wenn eine Ausnahme im verwalteten Code ausgelöst wird, bevor die Laufzeit den Aufrufstapel nach einem Ausnahmehandler in der Anwendungsdomäne durchsucht.

public:
 event EventHandler<System::Runtime::ExceptionServices::FirstChanceExceptionEventArgs ^> ^ FirstChanceException;
[add: System.Security.SecurityCritical]
[remove: System.Security.SecurityCritical]
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;
public event EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> FirstChanceException;
[<add: System.Security.SecurityCritical>]
[<remove: System.Security.SecurityCritical>]
member this.FirstChanceException : EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> 
member this.FirstChanceException : EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs> 
Public Custom Event FirstChanceException As EventHandler(Of FirstChanceExceptionEventArgs) 

Ereignistyp

Attribute

Beispiele

Im folgenden Beispiel wird eine Reihe von Anwendungsdomänen erstellt, die durch AD3benannt AD0 werden, mit einem Worker Objekt in jeder Anwendungsdomäne. Jedes Worker Objekt weist einen Verweis auf das Worker Objekt in der nächsten Anwendungsdomäne auf, mit Ausnahme der Worker in der letzten Anwendungsdomäne. Das FirstChanceException Ereignis wird in allen Anwendungsdomänen außer AD1behandelt.

Note

Zusätzlich zu diesem Beispiel, das First-Chance-Ausnahmebenachrichtigungen in mehreren Anwendungsdomänen veranschaulicht, finden Sie einfache Anwendungsfälle in How to: Receive First-Chance Exception Notifications.

Wenn die Anwendungsdomänen erstellt wurden, ruft die Standardanwendungsdomäne die TestException Methode für die erste Anwendungsdomäne auf. Jedes Worker Objekt ruft die TestException Methode für die nächste Anwendungsdomäne auf, bis zuletzt Worker eine Ausnahme ausgelöst wird, die entweder behandelt oder nicht behandelt wird. Daher durchläuft der aktuelle Thread alle Anwendungsdomänen und TestException wird dem Stapel in jeder Anwendungsdomäne hinzugefügt.

Wenn das letzte Worker Objekt die Ausnahme behandelt, wird das FirstChanceException Ereignis nur in der letzten Anwendungsdomäne ausgelöst. Die anderen Anwendungsdomänen erhalten niemals die Möglichkeit, die Ausnahme zu behandeln, sodass das Ereignis nicht ausgelöst wird.

Wenn das letzte Worker Objekt die Ausnahme nicht behandelt, wird das FirstChanceException Ereignis in jeder Anwendungsdomäne ausgelöst, die über einen Ereignishandler verfügt. Nachdem jeder Ereignishandler abgeschlossen ist, wird der Stapel fortgesetzt, bis die Ausnahme von der Standardanwendungsdomäne abgefangen wird.

Note

Um zu sehen, wie die Stapelanzeige wächst, wenn das Ereignis näher und näher an der Standardanwendungsdomäne ausgelöst wird, ändern Sie sich e.Exception.Messagee.Exception in den FirstChanceHandler Ereignishandlern. Beachten Sie, dass der Aufruf über TestException Anwendungsdomänengrenzen hinweg zweimal angezeigt wird: einmal für den Proxy und einmal für den 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
 */
open System
open System.Runtime.ExceptionServices

let firstChanceHandler _ (e: FirstChanceExceptionEventArgs) =
    printfn $"FirstChanceException event raised in {AppDomain.CurrentDomain.FriendlyName}: {e.Exception.Message}"

type Worker() =
    inherit MarshalByRefObject()

    let mutable w = Unchecked.defaultof<Worker>

    member _.Initialize(count, max) =
        // Handle the FirstChanceException event in all application domains except
        // AD1.
        if count <> 1 then
            AppDomain.CurrentDomain.FirstChanceException.AddHandler 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 then
            let next = count + 1
            let ad = AppDomain.CreateDomain("AD" + string next)
            w <-
                ad.CreateInstanceAndUnwrap(typeof<Worker>.Assembly.FullName, "Worker") :?> Worker
            w.Initialize(next, max)

    member _.TestException(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 isNull (box w) then
            w.TestException handled
        elif handled then
            try
                raise (ArgumentException $"Thrown in {AppDomain.CurrentDomain.FriendlyName}")
            with :? ArgumentException as ex ->
                printfn $"ArgumentException caught in {AppDomain.CurrentDomain.FriendlyName}: {ex.Message}"
        else
            raise (ArgumentException $"Thrown in {AppDomain.CurrentDomain.FriendlyName}")

AppDomain.CurrentDomain.FirstChanceException.AddHandler firstChanceHandler

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

printfn "\nThe last application domain throws an exception and catches it:\n"
w.TestException true

try
    printfn "\nThe last application domain throws an exception and does not catch it:\n"
    w.TestException false
with :? ArgumentException as ex ->
    printfn"ArgumentException caught in {AppDomain.CurrentDomain.FriendlyName}: {ex.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
 *)
Imports System.Reflection
Imports System.Runtime.ExceptionServices

Class Example

    Shared Sub Main()
    
        AddHandler AppDomain.CurrentDomain.FirstChanceException, AddressOf FirstChanceHandler

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

        Console.WriteLine(vbCrLf & "The last application domain throws an exception and catches it:")
        Console.WriteLine()
        w.TestException(true)

        Try
            Console.WriteLine(vbCrLf & 
                "The last application domain throws an exception and does not catch it:")
            Console.WriteLine()
            w.TestException(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

    Private ad As AppDomain = Nothing
    Private w As Worker = Nothing

    Public Sub Initialize(ByVal count As Integer, ByVal max As Integer)
    
        ' Handle the FirstChanceException event in all application domains except
        ' AD1.
        If count <> 1
        
            AddHandler AppDomain.CurrentDomain.FirstChanceException, AddressOf FirstChanceHandler

        End If

        ' Create another application domain, until the maximum is reached.
        ' Field w remains Nothing in the last application domain, as a signal 
        ' to TestException(). 
        If count < max
            Dim nextAD As Integer = count + 1
            ad = AppDomain.CreateDomain("AD" & nextAD)
            w = CType(ad.CreateInstanceAndUnwrap(
                      GetType(Worker).Assembly.FullName, "Worker"),
                      Worker)
            w.Initialize(nextAD, max)
        End If
    End Sub

    Public Sub TestException(ByVal handled As Boolean)
    
        ' 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 IsNot Nothing
        
            w.TestException(handled)

        Else If handled
        
            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

    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

' 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

Hinweise

Dieses Ereignis ist nur eine Benachrichtigung. Die Behandlung dieses Ereignisses behandelt die Ausnahme nicht oder wirkt sich auf die nachfolgende Ausnahmebehandlung in keiner Weise aus. Nachdem das Ereignis ausgelöst wurde und Ereignishandler aufgerufen wurden, beginnt die Common Language Runtime (CLR) mit der Suche nach einem Handler für die Ausnahme. FirstChanceException stellt die Anwendungsdomäne die erste Möglichkeit bereit, eine verwaltete Ausnahme zu untersuchen.

Das Ereignis kann pro Anwendungsdomäne behandelt werden. Wenn ein Thread beim Ausführen eines Aufrufs mehrere Anwendungsdomänen durchläuft, wird das Ereignis in jeder Anwendungsdomäne ausgelöst, die einen Ereignishandler registriert hat, bevor die CLR mit der Suche nach einem übereinstimmenden Ausnahmehandler in dieser Anwendungsdomäne beginnt. Nachdem das Ereignis behandelt wurde, wird eine Suche nach einem übereinstimmenden Ausnahmehandler in dieser Anwendungsdomäne durchgeführt. Wenn keine gefunden wird, wird das Ereignis in der nächsten Anwendungsdomäne ausgelöst.

Sie müssen alle Ausnahmen behandeln, die im Ereignishandler für das FirstChanceException Ereignis auftreten. FirstChanceException Andernfalls wird rekursiv ausgelöst. Dies kann zu einem Stapelüberlauf und einer Beendigung der Anwendung führen. Es wird empfohlen, Ereignishandler für dieses Ereignis als eingeschränkte Ausführungsbereiche (CERs) zu implementieren, um infrastrukturbezogene Ausnahmen wie Out-of-Memory- oder Stack Overflow zu behalten, während die Ausnahmebenachrichtigung verarbeitet wird.

Dieses Ereignis wird nicht für Ausnahmen ausgelöst, die eine Beschädigung des Prozesszustands angeben, z. B. Zugriffsverletzungen, es sei denn, der Ereignishandler ist sicherheitskritisch und weist das HandleProcessCorruptedStateExceptionsAttribute Attribut auf.

Die Common Language Runtime hält Threadabbrüche an, während dieses Benachrichtigungsereignis behandelt wird.

Gilt für:

Weitere Informationen