Porady: odbieranie powiadomień o wyjątkach pierwszej szansy
Uwaga
Ten artykuł jest specyficzny dla programu .NET Framework. Nie ma zastosowania do nowszych implementacji platformy .NET, w tym .NET 6 i nowszych wersji.
Zdarzenie FirstChanceExceptionAppDomain klasy umożliwia odbieranie powiadomienia, że zgłoszono wyjątek, zanim środowisko uruchomieniowe języka wspólnego rozpoczęło wyszukiwanie procedur obsługi wyjątków.
Zdarzenie jest wywoływane na poziomie domeny aplikacji. Wątek wykonywania może przechodzić przez wiele domen aplikacji, więc wyjątek, który nie jest obsługiwany w jednej domenie aplikacji, może być obsługiwany w innej domenie aplikacji. Powiadomienie odbywa się w każdej domenie aplikacji, która dodała procedurę obsługi dla zdarzenia, dopóki domena aplikacji nie obsłuży wyjątku.
Procedury i przykłady w tym artykule pokazują, jak otrzymywać powiadomienia o wyjątkach pierwszej szansy w prostym programie, który ma jedną domenę aplikacji i w utworzonej domenie aplikacji.
Aby zapoznać się z bardziej złożonym przykładem obejmującym kilka domen aplikacji, zobacz przykład zdarzenia FirstChanceException .
Otrzymywanie powiadomień o wyjątku pierwszej szansy w domyślnej domenie aplikacji
W poniższej procedurze punkt wejścia dla aplikacji, Main()
metoda, jest uruchamiany w domyślnej domenie aplikacji.
Aby zademonstrować powiadomienia o wyjątkach pierwszej szansy w domyślnej domenie aplikacji
Zdefiniuj program obsługi zdarzeń dla FirstChanceException zdarzenia przy użyciu funkcji lambda i dołącz go do zdarzenia. W tym przykładzie program obsługi zdarzeń wyświetla nazwę domeny aplikacji, w której obsłużono zdarzenie i właściwość wyjątku 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
Wyrzuć wyjątek i przechwyć go. Zanim środowisko uruchomieniowe zlokalizuj program obsługi wyjątków, FirstChanceException zostanie zgłoszone zdarzenie i wyświetli komunikat. Po tym komunikacie jest wyświetlany komunikat programu obsługi wyjątków.
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
Wyrzuć wyjątek, ale go nie przechwyć. Zanim środowisko uruchomieniowe wyszukuje program obsługi wyjątków, FirstChanceException zdarzenie jest wywoływane i wyświetla komunikat. Nie ma procedury obsługi wyjątków, więc aplikacja kończy działanie.
throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName); } }
Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName) End Sub End Class
Kod przedstawiony w pierwszych trzech krokach tej procedury tworzy kompletną aplikację konsolową. Dane wyjściowe aplikacji różnią się w zależności od nazwy pliku .exe, ponieważ nazwa domyślnej domeny aplikacji składa się z nazwy i rozszerzenia pliku .exe. Zobacz następujące informacje, aby uzyskać przykładowe dane wyjściowe.
/* 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()
Otrzymywanie powiadomień o wyjątku pierwszej szansy w innej domenie aplikacji
Jeśli program zawiera więcej niż jedną domenę aplikacji, możesz wybrać, które domeny aplikacji odbierają powiadomienia.
Aby otrzymywać powiadomienia o wyjątkach pierwszej szansy w utworzonej domenie aplikacji
Zdefiniuj program obsługi zdarzeń dla FirstChanceException zdarzenia. W tym przykładzie
static
użyto metody (Shared
metody w Visual Basic), która wyświetla nazwę domeny aplikacji, w której obsłużono zdarzenie i właściwość wyjątku 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
Utwórz domenę aplikacji i dodaj procedurę obsługi zdarzeń do FirstChanceException zdarzenia dla tej domeny aplikacji. W tym przykładzie domena aplikacji ma nazwę
AD1
.AppDomain ad = AppDomain.CreateDomain("AD1"); ad.FirstChanceException += FirstChanceHandler;
Dim ad As AppDomain = AppDomain.CreateDomain("AD1") AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler
To zdarzenie można obsłużyć w domyślnej domenie aplikacji w taki sam sposób.
static
Użyj właściwościMain()
(Shared
w visual basic), AppDomain.CurrentDomain aby uzyskać odwołanie do domyślnej domeny aplikacji.
Aby zademonstrować powiadomienia o wyjątkach pierwszej szansy w domenie aplikacji
Worker
Utwórz obiekt w domenie aplikacji utworzonej w poprzedniej procedurze. Klasa musi być publicznaWorker
i musi pochodzić z MarshalByRefObjectklasy , jak pokazano w pełnym przykładzie na końcu tego artykułu.Worker w = (Worker) ad.CreateInstanceAndUnwrap( typeof(Worker).Assembly.FullName, "Worker");
Dim w As Worker = CType(ad.CreateInstanceAndUnwrap( GetType(Worker).Assembly.FullName, "Worker"), Worker)
Wywołaj metodę
Worker
obiektu, która zgłasza wyjątek. W tym przykładzie metoda jest wywoływanaThrower
dwukrotnie. Po raz pierwszy argument metody totrue
, co powoduje, że metoda przechwyci własny wyjątek. Po raz drugi argument tofalse
, aMain()
metoda przechwytuje wyjątek w domyślnej domenie aplikacji.// 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
Umieść kod w metodzie,
Thrower
aby określić, czy metoda obsługuje własny wyjątek.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
Przykład
Poniższy przykład tworzy domenę aplikacji o nazwie AD1
i dodaje procedurę obsługi zdarzeń do zdarzenia domeny FirstChanceException aplikacji. Przykład tworzy wystąpienie Worker
klasy w domenie aplikacji i wywołuje metodę o nazwie Thrower
, która zgłasza błąd ArgumentException. W zależności od wartości argumentu metoda przechwytuje wyjątek lub nie może go obsłużyć.
Za każdym razem, Thrower
gdy metoda zgłasza wyjątek w AD1
pliku , FirstChanceException zdarzenie jest zgłaszane w AD1
elemecie , a program obsługi zdarzeń wyświetla komunikat. Następnie środowisko uruchomieniowe wyszukuje procedurę obsługi wyjątków. W pierwszym przypadku program obsługi wyjątków znajduje się w pliku AD1
. W drugim przypadku wyjątek jest nieobsługiwany w AD1
elemencie , a zamiast tego jest przechwycony w domyślnej domenie aplikacji.
Uwaga
Nazwa domyślnej domeny aplikacji jest taka sama jak nazwa pliku wykonywalnego.
Jeśli dodasz program obsługi zdarzenia FirstChanceException do domyślnej domeny aplikacji, zdarzenie zostanie zgłoszone i obsłużone, zanim domyślna domena aplikacji obsłuży wyjątek. Aby to zobaczyć, dodaj kod AppDomain.CurrentDomain.FirstChanceException += FirstChanceException;
c# (w Visual Basic, AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException
) na początku Main()
.
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