Procedura: ricevere notifiche di eccezioni first-chance
Nota
Questo articolo è specifico per .NET Framework. Non si applica alle implementazioni più recenti di .NET, incluse .NET 6 e versioni successive.
L'evento FirstChanceException della classe AppDomain consente di ricevere una notifica in cui si informa che è stata generata un'eccezione, prima che Common Language Runtime inizi a cercare gestori di eccezioni .
L'evento viene generato a livello di dominio dell'applicazione. Poiché un thread di esecuzione può passare attraverso più domini dell'applicazione, un'eccezione che non viene gestita in un dominio dell'applicazione può essere gestita in un altro dominio dell'applicazione. La notifica si verifica in ogni dominio dell'applicazione che ha aggiunto un gestore per l'evento fino a quando un dominio non gestisce l'eccezione.
Le procedure e gli esempi di questo articolo illustrano come ricevere notifiche di eccezioni first-chance in un programma semplice che include un solo dominio dell'applicazione e in un dominio dell'applicazione creato.
Per un esempio più complesso che riguarda più domini dell'applicazione, vedere l'esempio relativo all'evento FirstChanceException.
Ricezione di notifiche di eccezioni first-chance nel dominio dell'applicazione predefinito
Nella procedura seguente il punto di ingresso per l'applicazione, il metodo Main()
, viene eseguito nel dominio dell'applicazione predefinito.
Per visualizzare notifiche di eccezioni first-chance nel dominio dell'applicazione predefinito
Definire un gestore dell'evento per l'evento FirstChanceException usando una funzione lambda e collegarlo all'evento. In questo esempio il gestore dell'evento stampa il nome del dominio dell'applicazione in cui l'evento è stato gestito e la proprietà Message dell'eccezione.
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
Generare un'eccezione e rilevarla. Prima che il runtime individui il gestore di eccezioni, viene generato l'evento FirstChanceException che visualizza un messaggio. Questo messaggio è seguito dal messaggio visualizzato dal gestore di eccezioni.
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
Generare un'eccezione senza rilevarla. Prima che il runtime cerchi un gestore di eccezioni, viene generato l'evento FirstChanceException che visualizza un messaggio. Poiché non è presente alcun gestore di eccezioni, l'applicazione viene chiusa.
throw new ArgumentException("Thrown in " + AppDomain.CurrentDomain.FriendlyName); } }
Throw New ArgumentException("Thrown in " & AppDomain.CurrentDomain.FriendlyName) End Sub End Class
Il codice visualizzato nei primi tre passaggi di questa procedura forma un'applicazione console completa. L'output dell'applicazione varia a seconda del nome del file con estensione exe, perché il nome del dominio dell'applicazione predefinito è costituito dal nome e dall'estensione del file exe. Di seguito è illustrato un output di esempio.
/* 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()
Ricezione di notifiche di eccezioni first-chance in un altro dominio dell'applicazione
Se il programma contiene più domini di applicazione, è possibile specificare i domini di applicazione che ricevono le notifiche.
Per ricevere notifiche di eccezioni first-chance in un dominio dell'applicazione creato
Definire un gestore dell'evento per l'evento FirstChanceException. Questo esempio usa un metodo
static
(Shared
in Visual Basic) che stampa il nome del dominio dell'applicazione in cui l'evento viene gestito e la proprietà Message dell'eccezione.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
Creare un dominio dell'applicazione e aggiungere il gestore dell'evento all'evento FirstChanceException per il dominio dell'applicazione. In questo esempio il dominio dell'applicazione è denominato
AD1
.AppDomain ad = AppDomain.CreateDomain("AD1"); ad.FirstChanceException += FirstChanceHandler;
Dim ad As AppDomain = AppDomain.CreateDomain("AD1") AddHandler ad.FirstChanceException, AddressOf FirstChanceHandler
È possibile gestire questo evento nel dominio dell'applicazione predefinito nello stesso modo. Usare la proprietà
static
(Shared
in Visual Basic) AppDomain.CurrentDomain inMain()
per ottenere un riferimento al dominio dell'applicazione predefinito.
Per visualizzare notifiche di eccezioni first-chance nel dominio dell'applicazione
Creare un oggetto
Worker
nel dominio dell'applicazione creato nella procedura precedente. La classeWorker
deve essere pubblica e deve derivare da MarshalByRefObject, come illustrato nell'esempio completo alla fine di questo articolo.Worker w = (Worker) ad.CreateInstanceAndUnwrap( typeof(Worker).Assembly.FullName, "Worker");
Dim w As Worker = CType(ad.CreateInstanceAndUnwrap( GetType(Worker).Assembly.FullName, "Worker"), Worker)
Chiamare un metodo dell'oggetto
Worker
che genera un'eccezione. In questo esempio il metodoThrower
viene chiamato due volte. La prima volta, poiché l'argomento del metodo ètrue
, il metodo rileva la propria eccezione. La seconda volta, l'argomento èfalse
e il metodoMain()
rileva l'eccezione nel dominio dell'applicazione predefinito.// 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
Inserire codice nel metodo
Thrower
per controllare se il metodo gestisce la propria eccezione.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
Esempio
L'esempio seguente crea un dominio dell'applicazione denominato AD1
e aggiunge un gestore dell'evento all'evento FirstChanceException del dominio dell'applicazione. L'esempio crea un'istanza della classe Worker
nel dominio dell'applicazione e chiama un metodo denominato Thrower
che genera ArgumentException. A seconda del valore del proprio argomento, il metodo rileva l'eccezione o non riesce a gestirla.
Ogni volta che il metodo Thrower
genera un'eccezione in AD1
, viene generato l'evento FirstChanceException in AD1
e il gestore dell'evento visualizza un messaggio. Il runtime cerca quindi un gestore di eccezioni. Nel primo caso il gestore di eccezioni viene trovato in AD1
. Nel secondo caso anziché essere gestita in AD1
, l'eccezione viene rilevata nel dominio dell'applicazione predefinito.
Nota
Il nome del dominio dell'applicazione predefinito è uguale al nome dell'eseguibile.
Se si aggiunge un gestore per l'evento FirstChanceException al dominio dell'applicazione predefinito, l'evento viene generato e gestito prima che il dominio dell'applicazione predefinito gestisca l'eccezione. Per verificarlo, aggiungere il codice C# AppDomain.CurrentDomain.FirstChanceException += FirstChanceException;
(in Visual Basic, AddHandler AppDomain.CurrentDomain.FirstChanceException, FirstChanceException
) all'inizio di 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