Postupy: Přijímání oznámení o první odpovídající výjimce
Poznámka:
Tento článek je specifický pro rozhraní .NET Framework. Nevztahuje se na novější implementace .NET, včetně .NET 6 a novějších verzí.
Událost FirstChanceExceptionAppDomain třídy umožňuje obdržet oznámení, že došlo k výjimce dříve, než modul CLR (Common Language Runtime) začal hledat obslužné rutiny výjimek.
Událost se vyvolá na úrovni domény aplikace. Vlákno provádění může procházet více domén aplikace, takže výjimku, která je neošetřená v jedné doméně aplikace, by mohla být zpracována v jiné doméně aplikace. K oznámení dochází v každé doméně aplikace, která přidala obslužnou rutinu události, dokud doména aplikace nezpracuje výjimku.
Postupy a příklady v tomto článku ukazují, jak přijímat oznámení o výjimce první šance v jednoduchém programu, který má jednu doménu aplikace a v doméně aplikace, kterou vytvoříte.
Složitější příklad, který zahrnuje několik domén aplikace, najdete v příkladu FirstChanceException události.
Příjem oznámení o výjimce první šance ve výchozí doméně aplikace
V následujícím postupu se vstupní bod aplikace, Main()
metoda, spouští ve výchozí doméně aplikace.
Předvedení oznámení o výjimce první šance ve výchozí doméně aplikace
Definujte obslužnou rutinu FirstChanceException události pro událost pomocí funkce lambda a připojte ji k události. V tomto příkladu obslužná rutina události vytiskne název domény aplikace, kde byla událost zpracována, a vlastnost výjimky Message .
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
Vyvolá výjimku a zachytí ji. Než modul runtime vyhledá obslužnou rutinu výjimky, FirstChanceException vyvolá se událost a zobrazí zprávu. Za touto zprávou následuje zpráva zobrazená obslužnou rutinou výjimky.
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
Vyvolá výjimku, ale nezachyťte ji. Než modul runtime vyhledá obslužnou rutinu výjimky, FirstChanceException vyvolá se událost a zobrazí zprávu. Neexistuje žádná obslužná rutina výjimky, takže aplikace se ukončí.
throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName); } }
Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName) End Sub End Class
Kód zobrazený v prvních třech krocích tohoto postupu tvoří úplnou konzolovou aplikaci. Výstup aplikace se liší v závislosti na názvu souboru .exe, protože název výchozí domény aplikace se skládá z názvu a přípony souboru .exe. Ukázkový výstup najdete v následujícím příkladu.
/* 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()
Příjem oznámení o výjimce první šance v jiné doméně aplikace
Pokud váš program obsahuje více než jednu doménu aplikace, můžete zvolit, které domény aplikace přijímají oznámení.
Příjem oznámení o výjimce první šance v doméně aplikace, kterou vytvoříte
Definujte obslužnou rutinu FirstChanceException události pro událost. Tento příklad používá metodu
static
(Shared
metodu v jazyce Visual Basic), která vytiskne název domény aplikace, kde byla událost zpracována, a vlastnost výjimky Message .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
Vytvořte doménu aplikace a přidejte obslužnou rutinu události do události pro danou FirstChanceException doménu aplikace. V tomto příkladu je doména aplikace pojmenována
AD1
.AppDomain ad = AppDomain.CreateDomain("AD1"); ad.FirstChanceException += FirstChanceHandler;
Dim ad As AppDomain = AppDomain.CreateDomain("AD1") AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler
Tuto událost můžete zpracovat ve výchozí doméně aplikace stejným způsobem.
static
Pomocí vlastnostiMain()
(Shared
v jazyce Visual Basic) AppDomain.CurrentDomain získejte odkaz na výchozí doménu aplikace.
Předvedení oznámení o výjimce první šance v doméně aplikace
Vytvořte
Worker
objekt v doméně aplikace, kterou jste vytvořili v předchozím postupu. TřídaWorker
musí být veřejná a musí být odvozena od MarshalByRefObject, jak je znázorněno v úplném příkladu na konci tohoto článku.Worker w = (Worker) ad.CreateInstanceAndUnwrap( typeof(Worker).Assembly.FullName, "Worker");
Dim w As Worker = CType(ad.CreateInstanceAndUnwrap( GetType(Worker).Assembly.FullName, "Worker"), Worker)
Volání metody objektu
Worker
, který vyvolá výjimku. V tomto příkladuThrower
se metoda volá dvakrát. Argument metody jetrue
poprvé , což způsobí, že metoda zachytit vlastní výjimku. Druhý argument jefalse
aMain()
metoda zachytí výjimku ve výchozí doméně aplikace.// 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
Umístěte do metody kód
Thrower
, který určuje, jestli metoda zpracovává vlastní výjimku.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
Příklad
Následující příklad vytvoří doménu aplikace s názvem AD1
a přidá obslužnou rutinu události do události domény FirstChanceException aplikace. Příklad vytvoří instanci Worker
třídy v doméně aplikace a volá metodu s názvemThrower
, která vyvolá .ArgumentException V závislosti na hodnotě argumentu metoda buď zachytí výjimku, nebo ji nezpracuje.
Pokaždé, Thrower
když metoda vyvolá výjimku v AD1
, FirstChanceException událost je vyvolána AD1
v a obslužná rutina události zobrazí zprávu. Modul runtime pak vyhledá obslužnou rutinu výjimky. V prvním případě se obslužná rutina výjimky nachází v AD1
souboru . V druhém případě je výjimka neošetřená AD1
a místo toho je zachycena ve výchozí doméně aplikace.
Poznámka:
Název výchozí domény aplikace je stejný jako název spustitelného souboru.
Pokud přidáte obslužnou rutinu FirstChanceException události do výchozí domény aplikace, je událost vyvolána a zpracována před výchozí doménou aplikace zpracovává výjimku. Chcete-li to zobrazit, přidejte na začátek Main()
kódu AppDomain.CurrentDomain.FirstChanceException += FirstChanceException;
jazyka C# (v jazyce Visual BasicAddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException
) .
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