Nieobsłużone wyjątki w WPF

Domyślnie WPF wyświetla okno dialogowe nieobsłużonego błędu a następnie po przyciśnięciu przycisku aplikacja zostaje zamknięta. W poście zajmiemy jednak się przeładowaniem tego zachowania poprzez np. zapis błędu do pliku. W WPF możemy wykorzystać zdarzenie DispatcherUnhandledException(plik App.xaml.cs), która wywoływana jest dla nieobsłużonych wyjątków. Jeśli zatem w kodzie znajdzie się wywołanie throw bez klauzuli catch, zdarzenie DispatcherUnhandledException zostanie uruchomione. Przykład, plik app.xaml.cs

public partial class App : Application
{
    private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
    {
        // zapis do logów, wyświetlanie własnego okna błędów itp.
        e.Handled = true;
    }
}

app.xaml:

<Application x:Class="WpfApplication2.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             DispatcherUnhandledException="App_DispatcherUnhandledException"
             StartupUri="MainWindow.xaml">
    <Application.Resources>
         
    </Application.Resources>
</Application>

Ustawienie wartości e.Handled na true powoduje, że wyjątek zostanie potraktowany jako obsłużony. Jest to więc doskonałe miejsce na wyświetlenie wszelkich customowych okien dialogowych czy umieszczenie po prostu logger’a. W pliku XAML podpinamy tylko zdarzenie (DispatcherUnhandledException ).

Niestety powyższy kod będzie działał wyłącznie w sytuacji gdy to główny wątek wyrzuca wyjątek. Dla wszelkich innych wątków (np. w BackgroundWorker, Thread itp), metoda NIE zostanie wywołana. Jeśli zatem chcemy dodać obsługę wyjątków wyrzuconych w zewnętrznych wątkach, musimy:

  1. obsłużyć wyjątek w zewnętrznym wątku (catch),
  2. przekazać wyjątek poza wątek (czyli do głównego wątku)
  3. rethrow – wyrzucić ponownie wyjątek – w tym momencie zostanie już uruchomiona metoda App_DisptacherUnhandledException.

2 thoughts on “Nieobsłużone wyjątki w WPF”

  1. Zainteresowało mnie, że dla innych wątków metoda przechwytująca nie zostanie uruchomiona.
    Czy w WinForms (zdarzenie UnhandledException w ApplicationEvents) też tak jest?

  2. ThreadException z Application nie wylapie wyjatkow z innych watkow.
    Z kolei
    AppDomain.CurrentDomain.UnhandledException wylapie ale nie ma tam opcji handled.

Leave a Reply

Your email address will not be published.