AppDomain.FirstChanceException Ereignis
Definition
Wichtig
Einige Informationen beziehen sich auf Vorabversionen, die vor dem Release ggf. grundlegend überarbeitet werden. Microsoft übernimmt hinsichtlich der hier bereitgestellten Informationen keine Gewährleistungen, seien sie ausdrücklich oder konkludent.
Tritt auf, wenn eine Ausnahme in verwaltetem Code ausgelöst wird, bevor die Laufzeit in der Aufrufliste nach einem Ausnahmehandler in der Anwendungsdomäne sucht.
public:
event EventHandler<System::Runtime::ExceptionServices::FirstChanceExceptionEventArgs ^> ^ FirstChanceException;
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;
member this.FirstChanceException : EventHandler<System.Runtime.ExceptionServices.FirstChanceExceptionEventArgs>
[<add: System.Security.SecurityCritical>]
[<remove: System.Security.SecurityCritical>]
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 mit dem Namen durch AD0
AD3
erstellt, wobei in jeder Anwendungsdomäne ein Worker
-Objekt vorhanden ist. Jedes Worker
Objekt verfügt über einen Verweis auf das Worker
Objekt in der nächsten Anwendungsdomäne, mit Ausnahme der Worker
in der letzten Anwendungsdomäne. Das FirstChanceException Ereignis wird in allen Anwendungsdomänen mit Ausnahme AD1
von behandelt.
Hinweis
Zusätzlich zu diesem Beispiel, das Ausnahmebenachrichtigungen zum ersten Zufall in mehreren Anwendungsdomänen veranschaulicht, finden Sie einfache Anwendungsfälle unter Vorgehensweise: Empfangen First-Chance Ausnahmebenachrichtigungen.
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 die letzte Worker
eine Ausnahme auslöst, 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 verarbeitet, wird das FirstChanceException Ereignis nur in der letzten Anwendungsdomäne ausgelöst. Die anderen Anwendungsdomänen haben nie die Möglichkeit, die Ausnahme zu behandeln, sodass das Ereignis nicht ausgelöst wird.
Wenn das letzte Worker
Objekt die Ausnahme nicht verarbeitet, wird das FirstChanceException Ereignis in jeder Anwendungsdomäne ausgelöst, die über einen Ereignishandler verfügt. Nachdem jeder Ereignishandler abgeschlossen ist, wird der Stapel weiterhin entladen, bis die Ausnahme von der Standardanwendungsdomäne abgefangen wird.
Hinweis
Um zu sehen, wie die Stapelanzeige wächst, wenn das Ereignis näher an der Standardanwendungsdomäne ausgelöst wird, ändern Sie e.Exception.Message
in den FirstChanceHandler
Ereignishandlern ine.Exception
. Beachten Sie, dass beim TestException
Aufruf über 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 verarbeitet die Ausnahme nicht oder wirkt sich auf die nachfolgende Ausnahmebehandlung in keiner Weise aus. Nachdem das Ereignis ausgelöst und Ereignishandler aufgerufen wurden, beginnt die Common Language Runtime (CLR) mit der Suche nach einem Handler für die Ausnahme. FirstChanceException bietet der Anwendungsdomäne eine erste Möglichkeit, 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 nach einem übereinstimmenden Ausnahmehandler in dieser Anwendungsdomäne gesucht. 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ührungsregionen (CERs) zu implementieren, damit sich infrastrukturbezogene Ausnahmen, wie z. B. Arbeitsspeichermangel oder Stapelüberlauf, nicht auf den virtuellen Computer auswirken, während die Ausnahmebenachrichtigung verarbeitet wird.
Dieses Ereignis wird nicht für Ausnahmen ausgelöst, die auf eine Beschädigung des Prozesszustands hinweisen, z. B. Zugriffsverletzungen, es sei denn, der Ereignishandler ist sicherheitskritisch und verfügt über das HandleProcessCorruptedStateExceptionsAttribute -Attribut.
Die Common Language Runtime hält Threadabbrüche an, während dieses Benachrichtigungsereignis behandelt wird.