Vorgehensweise: Empfangen von Ausnahmebenachrichtigungen (erste Chance)
Hinweis
Dieser Artikel gilt für das .NET Framework. Er gilt nicht für neuere Implementierungen von .NET, einschließlich .NET 6 und höherer Versionen.
Mit dem FirstChanceException-Ereignis der AppDomain-Klasse erhalten Sie eine Benachrichtigung bezüglich einer ausgelösten Ausnahme, bevor die CLR mit der Suche nach Ausnahmehandlern beginnt.
Das Ereignis wird auf Ebene der Anwendungsdomäne ausgelöst. Ein Ausführungsthread kann verschiedene Anwendungsdomänen durchlaufen. Es ist also möglich, dass ein Ausnahmefehler aus einer Anwendungsdomäne in einer anderen behandelt wird. Die Benachrichtigung findet in jeder Anwendungsdomäne statt, die einen Handler für das Ereignis hinzugefügt hat, bis eine Anwendungsdomäne die Ausnahme behandelt.
Die Verfahren und Beispiele in diesem Artikel zeigen, wie Sie Benachrichtigungen über Ausnahmefehler der ersten Chance in einem einfachen Programm mit einer Anwendungsdomäne und in einer von Ihnen selbst erstellten Anwendungsdomäne erhalten.
Ein umfangreicheres Beispiel, das mehrere Anwendungsdomänen umfasst, finden Sie im Beispiel zum FirstChanceException-Ereignis.
Empfangen von Benachrichtigungen über Ausnahmefehler der ersten Chance in Standardanwendungsdomänen
In der folgenden Prozedur, dem Einstiegspunkt der Anwendung (Main()
-Methode), wird in der Standardanwendungsdomäne ausgeführt.
So demonstrieren Sie Benachrichtigungen über Ausnahmefehler der ersten Chance in der Standardanwendungsdomäne
Definieren Sie mithilfe einer Lambda-Funktion einen Ereignishandler für das FirstChanceException-Ereignis, und fügen Sie ihn an das Ereignis an. In diesem Beispiel gibt der Ereignishandler den Namen der Anwendungsdomäne, in der das Ereignis behandelt wurde, und die Message-Eigenschaft der Ausnahme aus.
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
Lösen Sie eine Ausnahme aus, und fangen Sie sie ab. Bevor die Runtime den Ausnahmehandler sucht, wird das FirstChanceException-Ereignis ausgelöst und eine Meldung angezeigt. Auf diese Nachricht folgt die Nachricht, die vom Ausnahmehandler angezeigt wird.
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
Lösen Sie eine Ausnahme aus, aber fangen Sie sie nicht ab. Bevor die Runtime nach einem Ausnahmehandler sucht, wird das FirstChanceException-Ereignis ausgelöst und eine Meldung angezeigt. Da es keinen Ausnahmehandler gibt, wird die Anwendung beendet.
throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName); } }
Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName) End Sub End Class
Der Code aus den ersten drei Schritten dieser Prozedur stellt eine vollständige Konsolenanwendung dar. Die Ausgabe der Anwendung variiert je nach dem Namen der ausführbaren Datei, denn der Name der Standardanwendungsdomäne besteht aus dem Namen und der Erweiterung der ausführbaren Datei. Ein Beispiel finden Sie in der folgenden Ausgabe.
/* 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()
Empfangen von Benachrichtigungen über Ausnahmefehler der ersten Chance in einer anderen Anwendungsdomäne
Wenn Ihr Programm mehr als eine Anwendungsdomäne enthält, können Sie auswählen, welche Anwendungsdomänen Benachrichtigungen erhalten.
So empfangen Sie Benachrichtigungen über Ausnahmefehler der ersten Chance in einer selbst erstellten Anwendungsdomäne
Definieren Sie einen Ereignishandler für das FirstChanceException-Ereignis. In diesem Beispiel wird eine
static
-Methode verwendet (Shared
-Methode in Visual Basic), die den Namen der Anwendungsdomäne, in der das Ereignis behandelt wurde, und die Message-Eigenschaft der Ausnahme ausgibt.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
Erstellen Sie eine Anwendungsdomäne, und fügen Sie dem FirstChanceException-Ereignis dieser Anwendungsdomäne den Ereignishandler hinzu. In diesem Beispiel heißt die Anwendungsdomäne
AD1
.AppDomain ad = AppDomain.CreateDomain("AD1"); ad.FirstChanceException += FirstChanceHandler;
Dim ad As AppDomain = AppDomain.CreateDomain("AD1") AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler
Sie können dieses Ereignis in der Standardanwendungsdomäne auf dieselbe Weise behandeln. Verwenden Sie die statische (
static
) AppDomain.CurrentDomain-Eigenschaft (Shared
in Visual Basic) inMain()
, um einen Verweis auf die Standardanwendungsdomäne abzurufen.
So demonstrieren Sie Benachrichtigungen über Ausnahmefehler der ersten Chance in der Anwendungsdomäne
Erstellen Sie ein
Worker
-Objekt in der Anwendungsdomäne, die Sie in der vorherigen Prozedur erstellt haben. DieWorker
-Klasse muss öffentlich und von MarshalByRefObject abgeleitet sein, wie im vollständigen Beispiel am Ende dieses Artikels dargestellt.Worker w = (Worker) ad.CreateInstanceAndUnwrap( typeof(Worker).Assembly.FullName, "Worker");
Dim w As Worker = CType(ad.CreateInstanceAndUnwrap( GetType(Worker).Assembly.FullName, "Worker"), Worker)
Rufen Sie eine Methode des
Worker
-Objekts auf, die eine Ausnahme auslöst. In diesem Beispiel wird dieThrower
-Methode zweimal aufgerufen. Beim ersten Aufruf lautet das Methodenargumenttrue
, weswegen die Methode ihre eigene Ausnahme abfängt. Beim zweiten Aufruf lautet das Argumentfalse
, und dieMain()
-Methode fängt die Ausnahme in der Standardanwendungsdomäne ab.// 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
Platzieren Sie Code in der
Thrower
-Methode, um zu steuern, ob die Methode ihre eigene Ausnahme behandelt.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
Beispiel
Im folgenden Beispiel wird eine Anwendungsdomäne namens AD1
erstellt und der Anwendungsdomäne des FirstChanceException-Ereignisses ein Ereignishandler hinzugefügt. Außerdem wird eine Instanz der Worker
-Klasse in der Anwendungsdomäne erstellt und eine Methode namens Thrower
aufgerufen, die ArgumentException auslöst. Je nach dem Wert des Arguments fängt die Methode die Ausnahme entweder ab, oder es tritt ein Fehler bei der Behandlung auf.
Jedes Mal, wenn die Thrower
-Methode eine Ausnahme in AD1
auslöst, wird das FirstChanceException-Ereignis in AD1
ausgelöst, und der Ereignishandler zeigt eine Meldung an. Die Runtime sucht nach einem Ausnahmehandler. Im ersten Fall befindet sich der Ausnahmehandler in AD1
. Im zweiten Fall wird die Ausnahme in AD1
nicht behandelt und stattdessen in der Standardanwendungsdomäne abgefangen.
Hinweis
Der Name der Standardanwendungsdomäne ist identisch mit dem Namen der ausführbaren Datei.
Wenn Sie der Standardanwendungsdomäne einen Handler für das FirstChanceException-Ereignis hinzufügen, wird das Ereignis ausgelöst und behandelt, bevor die Standardanwendungsdomäne die Ausnahme behandelt. Um dies zu veranschaulichen, fügen Sie den C#-Code AppDomain.CurrentDomain.FirstChanceException += FirstChanceException;
(in Visual Basic: AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException
) am Anfang von Main()
ein.
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