2011-01-26 30 views
12

WPF窗口对话框使用Window类中的ShowDialog方法显示,就像在主窗口上按下按钮一样,如下所示。WPF ShowDialog在窗口加载期间吞咽异常

 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上设置的类似开关?

+0

我试图重现您的情况,但没有成功。例外情况通常会被捕获。 我想,你已经简化了代码,但看起来主要点在细节。提供他们,我会尽力帮助。 – 2011-01-26 17:20:28

+0

感谢您试图重现。我从一个非常简单的例子中转载了这个问题,从我发布的源代码的位置开始。我使用VS2010。我将编辑我的问题并添加一些相关信息以进行复制。 – vidstige 2011-01-27 07:58:24

回答

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

我有类似的问题,并试图了解它来的地方是令人沮丧的。有几件事情可能会导致问题。

  • 你是否在方法调用InitializeComponent()之前调用任何东西? ?以前我有一个调用xaml元素的方法,尚未初始化。
  • 您是否尝试按F10启动应用程序,使用Step Over会让您看到确切的启动过程?
  • 你检查了你的命名吗? XAML可能会吞下错误,如方法被拼写错误,然后在运行时引发异常,这是特别真实的DataSet提供程序。你会惊讶什么,你可以摆脱。获取打开表单的异常非常重要,我宁愿查看任何依赖项(Data或XAML绑定)并首先处理它们。

希望这些点帮助.......

+0

*除问题中所述外,没有其他metod显示。 InitializeComponents在两个窗口的构造函数中都是独一无二的。 – vidstige 2011-01-27 13:48:13

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中设置一个断点,看看会发生什么 - 仔细注意调用堆栈。

祝你好运!

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位机器上验证它的答案。

2

“为什么”在这里解释: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进程(您需要使用Environment.Is64BitOperatingSystem而不是.NET 4及更高版本)时,IntPtr.Size将等于4。

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

永远不要在Winforms中使用Loaded(或OnLoad),因为如果在那里有异常,你不知道会发生什么。

看一看也是在这样的回答:https://stackoverflow.com/a/4934010/200443