Supponiamo di avere una semplice applicazione Windows Form il cui unico (e stupido) compito è quello di eseguire una divisione, qualcosa del tipo
Se non eseguiamo nessuna validazione sui campi, potrebbe accadere che vengano eseguiti calcoli sbagliati (ad esempio una divisione per zero) e di conseguenza che vengano sollevate le corrispondenti eccezioni. Per catturarle, possiamo utilizzare dei blocchi Try...Catch...Finally oppure gestire l'evento Application.ThreadException. Così facendo, oltre alla possibilità di memorizzare un log delle eccezioni a livello di applicazione o eseguire del codice di pulizia, possiamo visualizzare una Windows Form User-Friendly, senza interrompere bruscamente l'applicazione. Per registrare il gestore dell'evento ThreadException, possiamo aggiungere un modulo al nostro progetto e scrivere il seguente codice:
1 <STAThread()> _
2 Public Sub Main()
3
4 'Imposta il gestore evento Application.ThreadExeception personalizzato
5 AddHandler Application.ThreadException, AddressOf CustomErrorHandler
6
7 AddHandler AppDomain.CurrentDomain.UnhandledException, AddressOf AppDomainCustomErrorHandler
8
9 'Imposta il gestore evento Application.ApplicationExit personalizzato
10 AddHandler Application.ApplicationExit, AddressOf CustomApplicationExit
11
12 Application.Run(New Form1())
13 End Sub
Dove il gestore CustomErrorHandler è del tipo:
1 Public Sub CustomErrorHandler(ByVal sender As Object, ByVal e As System.Threading.ThreadExceptionEventArgs)
2
3 Try
4 'Gestisce l'eccezione visualizzando una finestra di dialogo comune per l'eventuali eccezioni
5 My.Forms.frmExeception.DescrizioneEccezione = e.Exception.Message
6 My.Forms.frmExeception.ShowDialog()
7 Catch ex As Exception
8
9 End Try
10
11 End Sub
Il quale, in caso di eccezione, visualizza la seguente finestra di dialogo:
Nel Sub Main, oltre a registrare l'evento Application.ThreadException, viene registrato anche il gestore per l'evento AppDomain.CurrentDomain.UnhandledExecption, perchè nel in cui caso la nostra applicazione sfrutti il multithreading, l'eventuali eccezioni dovute ai thread secondari non sarebbero catturate da CustomErrorHandler. Il codice del gestore per l'evento AppDomain.CurrrentDomain.UnhandledException è il seguente:
1 Public Sub AppDomainCustomErrorHandler(ByVal sender As Object, ByVal e As UnhandledExceptionEventArgs)
2 Try
3 'Gestisce l'eccezione visualizzando una finestra di dialogo comune per l'eventuali eccezioni
4 'Ottiene l'oggetto Exception
5 Dim appDomainException As Exception = DirectCast(e.ExceptionObject, System.Exception)
6 My.Forms.frmExeception.DescrizioneEccezione = appDomainException.Message
7 My.Forms.frmExeception.ShowDialog()
8
9 If (e.IsTerminating) Then
10 'Operazioni di pulizia...
11 End If
12 Catch ex As Exception
13
14 End Try
15 End Sub
Il quale esegue una cast dell'oggetto e.ExceptionObject in System.Exception e visualizza la finestra di dialogo su mostrata. L'istanza di oggetto UnhandledExecptionEventArgs espone la proprietà IsTerminating che indica se il common language runtime stà terminando o meno. Nel caso di UnhandledExecption, il .Net Framework , con o senza gestione del relativo evento, visualizza la classica finestra di dialogo per l'esecuzione del debug dell'applicazione. Per testare il codice ed il relativo comportamento dell'applicazione, da Visual Studio è necessario lanciare l'applicazione senza Debug.
Thread Exception.zip