WPF ShowDialog swallowing exceptions during window load

exceptionwpf

A WPF window dialog is shown using the ShowDialog method in the Window class like when a button is pressed on the main window, like this.

        private void button1_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                var window = new Window1();
                window.ShowDialog();
            }
            catch (ApplicationException ex)
            {
                MessageBox.Show("I am not shown.");
            }
        }

The window has a Loaded event subscribed in the xaml like this:

<Window x:Class="Stackoverflow.Window1"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Window1" Loaded="Window_Loaded">
    <Grid />
</Window>

An exception is thrown in the Window_Loaded event

    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        throw new ApplicationException();
    }

However the exception is not catched by the catch around the ShowDialog call, nor does the call return. The exception is swallowed and the window still displayed.

Why does this happen and how would I go about handling an exception in the Window_Loaded event of a WPF window? Do I have to catch it in the event-handler and Dispose the window manually?

In WinForms you need to call Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)

in order to let exceptions bubble through ShowDialog calls. Is there a similar switch that needs to be set on WPF?

Best Answer

I've only seen this issue on x64 machines, with code compiled with Any Cpu. Changing your program to compile as x84 may fix it, but I've had problems there myself depending on our assemblies.
My only code suggestion is the following, and even then it's not guaranteed to pick it up. Catch the exception, and re-throw it in a Background worker.

private void Window_Loaded(object sender, RoutedEventArgs e)
{
    try
    {
        /// your code here...
        throw new ApplicationException();
        /// your code here...
    }
    catch (Exception ex)
    {
        if (IntPtr.Size == 8)   // 64bit machines are unable to properly throw the errors during a Page_Loaded event.
        {
            BackgroundWorker loaderExceptionWorker = new BackgroundWorker();
            loaderExceptionWorker.DoWork += ((exceptionWorkerSender, runWorkerCompletedEventArgs) => { runWorkerCompletedEventArgs.Result = runWorkerCompletedEventArgs.Argument; });
            loaderExceptionWorker.RunWorkerCompleted += ((exceptionWorkerSender, runWorkerCompletedEventArgs) => { throw (Exception)runWorkerCompletedEventArgs.Result; });
            loaderExceptionWorker.RunWorkerAsync(ex);
        }
        else
            throw;
    }
}
Related Topic