AppDomain.FirstChanceException Esemény
Definíció
Fontos
Egyes információk olyan, kiadás előtti termékekre vonatkoznak, amelyek a kiadásig még jelentősen módosulhatnak. A Microsoft nem vállal kifejezett vagy törvényi garanciát az itt megjelenő információért.
Ez akkor fordul elő, ha kivételt ad a felügyelt kódban, mielőtt a futtatókörnyezet megkeresi a hívásvermet egy kivételkezelőben az alkalmazástartományban.
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)
Eseménytípus
- Attribútumok
Példák
Az alábbi példa egy olyan alkalmazástartomány-sorozatot hoz létre, amelyen keresztül AD0elneveznek AD3 egy Worker objektumot az egyes alkalmazástartományokban. Minden Worker objektum a következő alkalmazástartományban található objektumra Worker mutató hivatkozással rendelkezik, kivéve az Worker utolsó alkalmazástartományban lévő objektumot. Az FirstChanceException eseményt a rendszer az összes alkalmazástartományban kezeli, kivéve AD1.
Note
Ezen a példán kívül, amely több alkalmazástartományban mutatja be az első esélyű kivételértesítéseket, egyszerű használati eseteket is találhat a Hogyan: First-Chance kivételértesítések fogadása című témakörben.
Az alkalmazástartományok létrehozásakor az alapértelmezett alkalmazástartomány meghívja az TestException első alkalmazástartomány metódusát. Minden Worker objektum meghívja a TestException következő alkalmazástartomány metódusát, amíg az utolsó Worker kivétel nem lesz kezelve vagy kezeletlen. Így az aktuális szál áthalad az összes alkalmazástartományon, és TestException minden alkalmazástartományban hozzá lesz adva a veremhez.
Amikor az utolsó Worker objektum kezeli a kivételt, az FirstChanceException esemény csak az utolsó alkalmazástartományban lesz előállítva. A többi alkalmazástartomány soha nem tudja kezelni a kivételt, ezért az esemény nem jön létre.
Ha az utolsó Worker objektum nem kezeli a kivételt, az FirstChanceException esemény minden olyan alkalmazástartományban megjelenik, amely rendelkezik eseménykezelővel. Az egyes eseménykezelők befejeződése után a verem továbbra is visszateker, amíg a kivételt az alapértelmezett alkalmazástartomány el nem fogja kapni.
Note
Ha meg szeretné tekinteni, hogyan nő a verem megjelenítése az esemény az alapértelmezett alkalmazástartományhoz közelebb és közelebb kerül, váltson e.Exception.Messagee.Exception az FirstChanceHandler eseménykezelőkre. Figyelje meg, hogy ha TestException az alkalmazás tartományhatárai között van meghívva, kétszer jelenik meg: egyszer a proxyhoz, egyszer pedig a csonkhoz.
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
Megjegyzések
Ez az esemény csak egy értesítés. Az esemény kezelése semmilyen módon nem kezeli a kivételt, és semmilyen módon nem befolyásolja a későbbi kivételkezelést. Az esemény létrehozása és az eseménykezelők meghívása után a közös nyelvi futtatókörnyezet (CLR) elkezd keresni egy kezelőt a kivételhez. FirstChanceException lehetőséget biztosít az alkalmazástartomány számára a felügyelt kivételek vizsgálatára.
Az esemény alkalmazástartományonként kezelhető. Ha egy szál több alkalmazástartományon halad át egy hívás végrehajtása közben, az esemény minden olyan alkalmazástartományban létrejön, amely regisztrált egy eseménykezelőt, mielőtt a CLR elkezd keresni egy egyező kivételkezelőt az adott alkalmazástartományban. Az esemény kezelése után a rendszer keresést végez egy egyező kivételkezelőre az adott alkalmazástartományban. Ha egyik sem található, az esemény a következő alkalmazástartományban lesz előállítva.
Az esemény eseménykezelőjében előforduló összes kivételt FirstChanceException kezelnie kell. FirstChanceException Ellenkező esetben rekurzívan történik a felemelés. Ez a verem túlcsordulását és az alkalmazás leállítását eredményezheti. Javasoljuk, hogy az esemény eseménykezelői korlátozott végrehajtási régiókként (CER-ek) legyenek implementálva, hogy az infrastruktúrával kapcsolatos kivételek, például a memóriakihasználtság vagy a verem túlcsordulása ne befolyásolja a virtuális gépet a kivételértesítés feldolgozása során.
Ez az esemény nem merül fel a folyamatállapot sérülését jelző kivételek, például a hozzáférés megsértése esetén, kivéve, ha az eseménykezelő biztonsági szempontból kritikus fontosságú, és rendelkezik az HandleProcessCorruptedStateExceptionsAttribute attribútummal.
A közös nyelvi futtatókörnyezet felfüggeszti a szál megszakításait az értesítési esemény kezelése közben.