tipos - todas las excepciones en c#
Controlador de excepciones global de WPF (9)
Además de las publicaciones anteriores:
Application.Current.DispatcherUnhandledException
no capturará las excepciones que se lanzan desde otro hilo, luego el hilo principal. Tienes que manejar esas excepciones en su hilo real. Pero si desea manejarlos en su controlador de excepciones global, puede pasarlo al hilo principal:
System.Threading.Thread t = new System.Threading.Thread(() =>
{
try
{
...
//this exception will not be catched by
//Application.DispatcherUnhandledException
throw new Exception("huh..");
...
}
catch (Exception ex)
{
//But we can handle it in the throwing thread
//and pass it to the main thread wehre Application.
//DispatcherUnhandledException can handle it
System.Windows.Application.Current.Dispatcher.Invoke(
System.Windows.Threading.DispatcherPriority.Normal,
new Action<Exception>((exc) =>
{
throw new Exception("Exception from another Thread", exc);
}), ex);
}
});
Esta pregunta ya tiene una respuesta aquí:
A veces, bajo circunstancias no reproducibles, mi aplicación WPF se bloquea sin ningún mensaje. La aplicación simplemente se cierra al instante.
¿Dónde está el mejor lugar para implementar el bloque global Try / Catch? Al menos tengo que implementar un buzón de mensajes con: "Disculpe las molestias ..."
Como se ha mencionado más arriba
Application.Current.DispatcherUnhandledException no detectará las excepciones que se lanzan desde otro subproceso que el subproceso principal.
Eso depende realmente de cómo se creó el hilo
Un caso que no es manejado por Application.Current.DispatcherUnhandledException es System.Windows.Forms.Timer para el cual se puede usar Application.ThreadException si ejecuta Formularios en otros subprocesos distintos del hilo principal que necesitará para establecer Application.ThreadException de cada uno de esos hilos
La mejor respuesta es probablemente https://.com/a/1472562/601990 .
Aquí hay un código que muestra cómo usarlo:
App.xaml.cs
public sealed partial class App
{
protected override void OnStartup(StartupEventArgs e)
{
// setting up the Dependency Injection container
var resolver = ResolverFactory.Get();
// getting the ILogger or ILog interface
var logger = resolver.Resolve<ILogger>();
RegisterGlobalExceptionHandling(logger);
// Bootstrapping Dependency Injection
// injects ViewModel into MainWindow.xaml
// remember to remove the StartupUri attribute in App.xaml
var mainWindow = resolver.Resolve<Pages.MainWindow>();
mainWindow.Show();
}
private void RegisterGlobalExceptionHandling(ILogger log)
{
// this is the line you really want
AppDomain.CurrentDomain.UnhandledException +=
(sender, args) => CurrentDomainOnUnhandledException(args, log);
// optional: hooking up some more handlers
// remember that you need to hook up additional handlers when
// logging from other dispatchers, shedulers, or applications
Application.Dispatcher.UnhandledException +=
(sender, args) => DispatcherOnUnhandledException(args, log);
Application.Current.DispatcherUnhandledException +=
(sender, args) => CurrentOnDispatcherUnhandledException(args, log);
TaskScheduler.UnobservedTaskException +=
(sender, args) => TaskSchedulerOnUnobservedTaskException(args, log);
}
private static void TaskSchedulerOnUnobservedTaskException(UnobservedTaskExceptionEventArgs args, ILogger log)
{
log.Error(args.Exception, args.Exception.Message);
args.SetObserved();
}
private static void CurrentOnDispatcherUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)
{
log.Error(args.Exception, args.Exception.Message);
// args.Handled = true;
}
private static void DispatcherOnUnhandledException(DispatcherUnhandledExceptionEventArgs args, ILogger log)
{
log.Error(args.Exception, args.Exception.Message);
// args.Handled = true;
}
private static void CurrentDomainOnUnhandledException(UnhandledExceptionEventArgs args, ILogger log)
{
var exception = args.ExceptionObject as Exception;
var terminatingMessage = args.IsTerminating ? " The application is terminating." : string.Empty;
var exceptionMessage = exception?.Message ?? "An unmanaged exception occured.";
var message = string.Concat(exceptionMessage, terminatingMessage);
log.Error(exception, message);
}
}
Para complementar la respuesta de Thomas, la clase de Application
también tiene el evento Application.DispatcherUnhandledException que puede manejar.
Puedes atrapar excepciones no manejadas en diferentes niveles:
- AppDomain.UnhandledException De todos los subprocesos en el dominio de aplicación.
-
Dispatcher.UnhandledException
Desde un único subproceso de distribuidor de IU específico. - Application.DispatcherUnhandledException Desde el subproceso principal de UI dispatcher en su aplicación WPF.
-
TaskScheduler.UnobservedTaskException
desde cada AppDomain que usa un programador de tareas para operaciones asíncronas.
Debe considerar en qué nivel necesita atrapar las excepciones no manejadas.
La decisión entre el # 2 y el # 3 depende de si está utilizando más de un subproceso de WPF. Esta es una situación bastante exótica y si no está seguro de si lo está o no, entonces es muy probable que no lo esté.
Un ejemplo rápido de código para Application.Dispatcher.UnhandledException:
public App() {
this.Dispatcher.UnhandledException += OnDispatcherUnhandledException;
}
void OnDispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e) {
string errorMessage = string.Format("An unhandled exception occurred: {0}", e.Exception.Message);
MessageBox.Show(errorMessage, "Error", MessageBoxButton.OK, MessageBoxImage.Error);
e.Handled = true;
}
Agregué este código en App.xaml.cs
Una solución completa está here
Se explica muy bien con código de ejemplo. Sin embargo, tenga cuidado de que no cierre la aplicación. Agregue la línea Application.Current.Shutdown (); para cerrar con gracia la aplicación.
Utilizo el siguiente código en mis aplicaciones WPF para mostrar un cuadro de diálogo "Disculpe las molestias" cada vez que se produce una excepción no controlada. Muestra el mensaje de excepción y pregunta al usuario si desea cerrar la aplicación o ignorar la excepción y continuar (este último caso es conveniente cuando se producen excepciones no fatales y el usuario todavía puede continuar usando la aplicación).
En App.xaml agregue el controlador de eventos de inicio:
<Application .... Startup="Application_Startup">
En el código App.xaml.cs, agregue la función de controlador de eventos de inicio que registrará el controlador de eventos de aplicación global:
using System.Windows.Threading;
private void Application_Startup(object sender, StartupEventArgs e)
{
// Global exception handling
Application.Current.DispatcherUnhandledException += new DispatcherUnhandledExceptionEventHandler(AppDispatcherUnhandledException);
}
void AppDispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
/#if DEBUG // In debug mode do not custom-handle the exception, let Visual Studio handle it
e.Handled = false;
/#else
ShowUnhandledException(e);
/#endif
}
void ShowUnhandledException(DispatcherUnhandledExceptionEventArgs e)
{
e.Handled = true;
string errorMessage = string.Format("An application error occurred./nPlease check whether your data is correct and repeat the action. If this error occurs again there seems to be a more serious malfunction in the application, and you better close it./n/nError: {0}/n/nDo you want to continue?/n(if you click Yes you will continue with your work, if you click No the application will close)",
e.Exception.Message + (e.Exception.InnerException != null ? "/n" +
e.Exception.InnerException.Message : null));
if (MessageBox.Show(errorMessage, "Application Error", MessageBoxButton.YesNoCancel, MessageBoxImage.Error) == MessageBoxResult.No) {
if (MessageBox.Show("WARNING: The application will close. Any changes will not be saved!/nDo you really want to close it?", "Close the application!", MessageBoxButton.YesNoCancel, MessageBoxImage.Warning) == MessageBoxResult.Yes)
{
Application.Current.Shutdown();
}
}
Puede manejar el evento AppDomain.UnhandledException
EDIT: en realidad, este evento es probablemente más adecuado: Application.DispatcherUnhandledException