WPF ShowDialog在窗口加载期间吞咽异常

时间:2011-01-26 16:33:43

标签: wpf exception

使用Window类中的ShowDialog方法显示WPF窗口对话框,就像在主窗口上按下按钮一样,就像这样。

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

该窗口在xaml中订阅了一个Loaded事件,如下所示:

<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>

Window_Loaded事件

中抛出异常
    private void Window_Loaded(object sender, RoutedEventArgs e)
    {
        throw new ApplicationException();
    }

然而,ShowDialog调用周围没有捕获异常,调用也没有返回。吞下异常,窗口仍然显示。

为什么会发生这种情况?如何在WPF窗口的Window_Loaded事件中处理异常?我是否必须在事件处理程序中捕获它并手动处理窗口?

在WinForms中,您需要致电Application.SetUnhandledExceptionMode(UnhandledExceptionMode.ThrowException)

为了让异常通过ShowDialog调用冒泡。是否需要在WPF上设置类似的开关?

5 个答案:

答案 0 :(得分:7)

我在x64机器上只看到过这个问题,代码是用Any Cpu编译的。 将程序改为编译为x84可能会修复它,但我自己也有问题,这取决于我们的程序集 我唯一的代码建议如下,即便如此,也不保证能够提取它。 捕获异常,并将其重新抛出后台工作程序。

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

答案 1 :(得分:2)

&#34;为什么&#34;这里解释:http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

简而言之,异常无法在64位操作系统中传播,因为用户和内核模式之间存在转换。

在@midspace中测试IntPtr.Size是不够的,因为在x64操作系统上运行的x86进程中IntPtr.Size将等于4(你需要在.NET 4上使用Environment.Is64BitOperatingSystem而不是更大)。

现在的解决方案:使用ContentRendered之类的另一个事件,在Loaded之后调用,或者将代码放在窗口构造函数中。

永远不要在Winforms中使用Loaded(或OnLoad),因为如果有例外情况,您就不知道会发生什么。

还要看一下这个答案:https://stackoverflow.com/a/4934010/200443

答案 2 :(得分:1)

我还在一个空白的WPF 3.5项目中重构了Visual Studio 2010中的答案。

项目按预期运行,即Window_Loaded抛出异常,它被按钮点击事件捕获。

所以我不确定你为什么不工作,也许试着发布你的App.xml.cs和你没有在这里展示的任何其他代码?

与此同时,我想我会指出一些事情:

WPF确实处理“未捕获”异常与WinForms略有不同。试着看看这个首发:

http://msdn2.microsoft.com/en-us/library/system.windows.application.dispatcherunhandledexception.aspx

看起来在WPF中没有SetUnhandledExceptionMode方法的精确等价物(参见http://social.msdn.microsoft.com/forums/en-US/wpf/thread/955c75f8-9cd9-4158-bed9-544bd7946413)。试试他们关于注册处理程序的建议,看看这对你有帮助吗?

我建议单步执行代码 - 在Window_Loaded中设置断点,看看会发生什么 - 注意调用堆栈。

祝你好运!

答案 3 :(得分:1)

研究这一点我发现这个特殊的博客条目描述了类似的问题。

http://blog.paulbetts.org/index.php/2010/07/20/the-case-of-the-disappearing-onload-exception-user-mode-callback-exceptions-in-x64/

事实证明它可能是64位处理器架构问题。谁会猜到?!这可能解释了为什么有些人无法重现这个问题我的简单例子。我试图在“任何CPU”,x64和x86中编译我的例子,但无济于事。在x64上,整个事情实际上已经爆炸,完全崩溃了Windows崩溃对话框。

所以我猜这是没有在32位机器上进行验证的答案。

答案 4 :(得分:0)

我遇到了类似的问题,试图了解它的来源令人沮丧。有几件事可能会导致问题。

  • 您是否在方法调用InitializeComponent()之前调用任何内容; ?以前我有一个调用xaml元素的方法,它尚未初始化。
  • 您是否尝试按F10启动应用程序,使用Step Over会让您看到确切的启动过程?
  • 你检查了你的命名吗? XAML可以吞下错误,例如错误拼写的方法,然后在运行时抛出异常,这尤其是真正的DataSet提供程序。你会惊讶于你可以逃脱的事情。
  • 获取打开表单的异常非常重要,我宁愿查看任何依赖项(数据或XAML绑定)并先处理它们。

希望这些要点有用.......