使用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上设置类似的开关?
答案 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
),因为如果有例外情况,您就不知道会发生什么。
答案 2 :(得分:1)
我还在一个空白的WPF 3.5项目中重构了Visual Studio 2010中的答案。
项目按预期运行,即Window_Loaded抛出异常,它被按钮点击事件捕获。
所以我不确定你为什么不工作,也许试着发布你的App.xml.cs和你没有在这里展示的任何其他代码?
与此同时,我想我会指出一些事情:
WPF确实处理“未捕获”异常与WinForms略有不同。试着看看这个首发:
看起来在WPF中没有SetUnhandledExceptionMode方法的精确等价物(参见http://social.msdn.microsoft.com/forums/en-US/wpf/thread/955c75f8-9cd9-4158-bed9-544bd7946413)。试试他们关于注册处理程序的建议,看看这对你有帮助吗?
我建议单步执行代码 - 在Window_Loaded中设置断点,看看会发生什么 - 注意调用堆栈。
祝你好运!答案 3 :(得分:1)
研究这一点我发现这个特殊的博客条目描述了类似的问题。
事实证明它可能是64位处理器架构问题。谁会猜到?!这可能解释了为什么有些人无法重现这个问题我的简单例子。我试图在“任何CPU”,x64和x86中编译我的例子,但无济于事。在x64上,整个事情实际上已经爆炸,完全崩溃了Windows崩溃对话框。
所以我猜这是没有在32位机器上进行验证的答案。
答案 4 :(得分:0)
我遇到了类似的问题,试图了解它的来源令人沮丧。有几件事可能会导致问题。
希望这些要点有用.......