WPF global exception handler [duplikat]

To pytanie ma już odpowiedź tutaj:

Czasami, w nie powtarzalnych okolicznościach, moja aplikacja WPF ulega awarii bez żadnej wiadomości. Aplikacja po prostu zamyka się natychmiast.

Gdzie jest najlepsze miejsce do wdrożenia globalnego bloku Try/Catch. Przynajmniej muszę zaimplementuj messagebox z: "przepraszamy za niedogodności ..."

Author: Jakob Möllås, 2009-09-24

9 answers

Możesz poradzić sobie z AppDomain.UnhandledException event

EDIT: właściwie to wydarzenie jest chyba bardziej adekwatne: Application.DispatcherUnhandledException

 145
Author: Thomas Levesque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-24 15:50:17

Możesz uwięzić nieobsługiwane wyjątki na różnych poziomach:

  1. AppDomain.CurrentDomain.UnhandledException ze wszystkich wątków w AppDomain.
  2. Dispatcher.UnhandledException z jednego konkretnego wątku dyspozytora interfejsu użytkownika.
  3. Application.Current.DispatcherUnhandledException z wątku Main UI dispatcher w Twojej aplikacji WPF.
  4. TaskScheduler.UnobservedTaskException z poziomu każdej domeny AppDomain, która używa harmonogramu zadań do operacji asynchronicznych.

Powinieneś rozważyć, jaki poziom potrzebujesz, aby uwięzić nieobsadzonego wyjątki w.

Wybór pomiędzy #2 a # 3 zależy od tego, czy używasz więcej niż jednego wątku WPF. Jest to dość egzotyczna sytuacja i jeśli nie jesteś pewien, czy jesteś, czy nie, to najprawdopodobniej nie jesteś.

 453
Author: Drew Noakes,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-17 17:07:59

Szybki przykład kodu aplikacji.Dyspozytor.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;
}

Dodałem ten kod w aplikacji.xaml.cs

 101
Author: Sergey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-09-22 05:53:51

Używam poniższego kodu w moich aplikacjach WPF, aby wyświetlić okno dialogowe "przepraszam za niedogodności" za każdym razem, gdy wystąpi nieobsługiwany wyjątek. Wyświetla komunikat o wyjątku i pyta użytkownika, czy chce zamknąć aplikację, czy zignorować wyjątek i kontynuować (ten drugi przypadek jest wygodny, gdy wystąpią wyjątki inne niż fatalne i użytkownik może nadal normalnie korzystać z aplikacji).

W Aplikacji.xaml dodaje obsługę zdarzenia startowego:

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

W Aplikacji.xaml.kod cs dodaj obsługę zdarzenia startowego funkcja, która zarejestruje globalną obsługę zdarzeń aplikacji:

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();
    } 
}
 40
Author: jurev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-09 06:33:10

Najlepsza odpowiedź to prawdopodobnie https://stackoverflow.com/a/1472562/601990 .

Oto kod, który pokazuje jak go używać:

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);
    }
}
 12
Author: MovGP0,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 11:33:26

Oprócz postów powyżej:

Application.Current.DispatcherUnhandledException

Nie wyłapuje wyjątków, które są wyrzucane z innego wątku niż główny wątek. Musisz obsłużyć te wyjątki w rzeczywistym wątku. Ale jeśli chcesz je obsługiwać w globalnym programie obsługi wyjątków, możesz przekazać je do głównego wątku:

 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);
        }
    });
 11
Author: Tobias Hoefer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-18 16:03:03

Aby uzupełnić odpowiedź Tomasza, klasa Application ma również DispatcherUnhandledException wydarzenie, z którym sobie poradzisz.

 3
Author: dustyburwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-09-24 15:52:55

Kompletne rozwiązanie to tutaj

Jest to bardzo ładnie wyjaśnione za pomocą przykładowego kodu. Należy jednak uważać, aby aplikacja nie została zamknięta.Dodaj wiersz Podanie.Aktualne.Shutdown(); aby z wdziękiem zamknąć aplikację.

 3
Author: karpanai,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-08 10:53:28

Jak wspomniano powyżej

Zastosowanie.Aktualne.DispatcherUnhandledException nie złapie wyjątki, które są wyrzucane z innego wątku, a następnie głównego wątku.

To zależy od tego jak wątek został utworzony

Jeden przypadek, który nie jest obsługiwany przez aplikację.Aktualne.DispatcherUnhandledException jest systemem.Okna.Formularze.Timer dla jakiej aplikacji.ThreadException może być używany do obsługi tych jeśli uruchomisz formularze w innych wątkach niż główny wątek, będziesz trzeba ustawić aplikację.ThreadException from each such thread

 1
Author: Jens,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-09-11 11:16:46