AppDomain.FirstChanceException Gebeurtenis
Definitie
Belangrijk
Bepaalde informatie heeft betrekking op een voorlopige productversie die aanzienlijk kan worden gewijzigd voordat deze wordt uitgebracht. Microsoft biedt geen enkele expliciete of impliciete garanties met betrekking tot de informatie die hier wordt verstrekt.
Treedt op wanneer er een uitzondering wordt gegenereerd in beheerde code, voordat de runtime de aanroepstack doorzoekt op een uitzonderingshandler in het toepassingsdomein.
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)
Gebeurtenistype
- Kenmerken
Voorbeelden
In het volgende voorbeeld wordt een reeks toepassingsdomeinen gemaakt met de naam AD0AD3, met een Worker object in elk toepassingsdomein. Elk Worker object heeft een verwijzing naar het object in het Worker volgende toepassingsdomein, met uitzondering van het Worker laatste toepassingsdomein. De FirstChanceException gebeurtenis wordt verwerkt in alle toepassingsdomeinen, met uitzondering van AD1.
Note
Naast dit voorbeeld, waarin uitzonderingsmeldingen voor de eerste kans in meerdere toepassingsdomeinen worden gedemonstreert, kunt u eenvoudige gebruiksvoorbeelden vinden in Procedures: Ontvangen First-Chance Uitzonderingsmeldingen.
Wanneer de toepassingsdomeinen zijn gemaakt, roept het standaardtoepassingsdomein de TestException methode aan voor het eerste toepassingsdomein. Elk Worker object roept de TestException methode aan voor het volgende toepassingsdomein, totdat de laatste Worker een uitzondering genereert die wordt verwerkt of niet-verwerkt. De huidige thread doorloopt dus alle toepassingsdomeinen en TestException wordt toegevoegd aan de stack in elk toepassingsdomein.
Wanneer het laatste Worker object de uitzondering afhandelt, wordt de FirstChanceException gebeurtenis alleen gegenereerd in het laatste toepassingsdomein. De andere toepassingsdomeinen krijgen nooit de kans om de uitzondering af te handelen, dus de gebeurtenis wordt niet gegenereerd.
Wanneer het laatste Worker object de uitzondering niet afhandelt, wordt de FirstChanceException gebeurtenis gegenereerd in elk toepassingsdomein met een gebeurtenis-handler. Nadat elke gebeurtenis-handler is voltooid, blijft de stack tot rust komen totdat de uitzondering wordt opgevangen door het standaardtoepassingsdomein.
Note
Als u wilt zien hoe de stackweergave toeneemt naarmate de gebeurtenis dichter en dichter bij het standaardtoepassingsdomein wordt gegenereerd, wijzigt e.Exception.Messagee.Exception u deze in de FirstChanceHandler gebeurtenis-handlers. U ziet dat wanneer de grenzen TestException van het toepassingsdomein worden aangeroepen, deze twee keer wordt weergegeven: eenmaal voor de proxy en eenmaal voor de 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
Opmerkingen
Deze gebeurtenis is alleen een melding. Het afhandelen van deze gebeurtenis verwerkt de uitzondering niet of heeft geen invloed op de daaropvolgende verwerking van uitzonderingen. Nadat de gebeurtenis is gegenereerd en gebeurtenis-handlers zijn aangeroepen, begint de COMMON Language Runtime (CLR) te zoeken naar een handler voor de uitzondering. FirstChanceException biedt het toepassingsdomein een eerste kans om een beheerde uitzondering te onderzoeken.
De gebeurtenis kan per toepassingsdomein worden verwerkt. Als een thread meerdere toepassingsdomeinen doorgeeft tijdens het uitvoeren van een aanroep, wordt de gebeurtenis gegenereerd in elk toepassingsdomein dat een gebeurtenis-handler heeft geregistreerd, voordat de CLR begint te zoeken naar een overeenkomende uitzonderingshandler in dat toepassingsdomein. Nadat de gebeurtenis is verwerkt, wordt er gezocht naar een overeenkomende uitzonderingshandler in dat toepassingsdomein. Als er geen wordt gevonden, wordt de gebeurtenis gegenereerd in het volgende toepassingsdomein.
U moet alle uitzonderingen afhandelen die optreden in de gebeurtenis-handler voor de FirstChanceException gebeurtenis. Anders wordt FirstChanceException recursief verhoogd. Dit kan leiden tot een stack-overloop en beƫindiging van de toepassing. We raden u aan gebeurtenis-handlers voor deze gebeurtenis te implementeren als beperkte uitvoeringsregio's (CER's), om infrastructuurgerelateerde uitzonderingen, zoals onvoldoende geheugen of stack-overloop, van invloed te houden op de virtuele machine terwijl de uitzonderingsmelding wordt verwerkt.
Deze gebeurtenis wordt niet gegenereerd voor uitzonderingen die duiden op beschadiging van de processtatus, zoals toegangsschendingen, tenzij de gebeurtenis-handler beveiligingskritiek is en het HandleProcessCorruptedStateExceptionsAttribute kenmerk heeft.
De algemene taalruntime onderbreekt threads terwijl deze meldingsgebeurtenis wordt verwerkt.