381 Stimmen

WPF global exception handler

Manchmal, unter nicht reproduzierbaren Umständen, stürzt meine WPF-Anwendung ohne Meldung ab. Die Anwendung einfach sofort schließen.

Wo ist der beste Ort, um den globalen Try/Catch-Block zu implementieren? Zumindest muss ich eine Messagebox mit implementieren: "Sorry for the inconvenience ..."

555voto

Drew Noakes Punkte 282438

Sie können unbehandelte Ausnahmen auf verschiedenen Ebenen abfangen:

  1. AppDomain.CurrentDomain.UnhandledException Von allen Threads in der AppDomain.
  2. Dispatcher.UnhandledException Von einem einzigen spezifischen UI-Dispatcher-Thread aus.
  3. Application.Current.DispatcherUnhandledException Von der Haupt UI-Dispatcher-Thread in Ihrer WPF-Anwendung.
  4. TaskScheduler.UnobservedTaskException aus jeder AppDomain, die einen Taskplaner für asynchrone Operationen verwendet.

Sie sollten überlegen, auf welcher Ebene Sie unbehandelte Ausnahmen abfangen müssen.

Die Entscheidung zwischen #2 und #3 hängt davon ab, ob Sie mehr als einen WPF-Thread verwenden. Dies ist eine ziemlich exotische Situation und wenn Sie unsicher sind, ob Sie sind oder nicht, dann ist es sehr wahrscheinlich, dass Sie nicht sind.

176voto

Thomas Levesque Punkte 277723

Sie können die AppDomain.UnhandledException Veranstaltung

EDIT: Eigentlich ist dieses Ereignis wahrscheinlich besser geeignet: Application.DispatcherUnhandledException

136voto

Sergey Punkte 1757

Ein kurzes Codebeispiel für 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);
    // OR whatever you want like logging etc. MessageBox it's just example
    // for quick debugging etc.
    e.Handled = true;
}

Ich habe folgenden Code in App.xaml.cs hinzugefügt

45voto

jurev Punkte 949

Ich verwende den folgenden Code in meinen WPF-Anwendungen, um ein Dialogfeld "Entschuldigung für die Unannehmlichkeiten" anzuzeigen, wenn eine unbehandelte Ausnahme auftritt. Es zeigt die Ausnahmemeldung an und fragt den Benutzer, ob er die Anwendung schließen oder die Ausnahme ignorieren und fortfahren möchte (der letztere Fall ist praktisch, wenn eine nicht tödliche Ausnahme auftritt und der Benutzer die Anwendung normal weiter verwenden kann).

Fügen Sie in App.xaml den Startup-Event-Handler hinzu:

<Application .... Startup="Application_Startup">

Fügen Sie im Code App.xaml.cs die Funktion Startup event handler hinzu, die den globalen Anwendungs-Ereignishandler registrieren wird:

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();
    } 
}

20voto

MovGP0 Punkte 6480

Die beste Antwort ist wahrscheinlich https://stackoverflow.com/a/1472562/601990 .

Hier ist ein Code, der zeigt, wie man ihn verwendet:

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);
    }
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X