WPF ShowDialog在窗口加载期间吞咽异常
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="*.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上设置的类似开关?
我只在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;
}
}
我有类似的问题,并试图了解它来的地方是令人沮丧的。有几件事情可能会导致问题。
- 你是否在方法调用InitializeComponent()之前调用任何东西? ?以前我有一个调用xaml元素的方法,尚未初始化。
- 您是否尝试按F10启动应用程序,使用Step Over会让您看到确切的启动过程?
- 你检查了你的命名吗? XAML可能会吞下错误,如方法被拼写错误,然后在运行时引发异常,这是特别真实的DataSet提供程序。你会惊讶什么,你可以摆脱。获取打开表单的异常非常重要,我宁愿查看任何依赖项(Data或XAML绑定)并首先处理它们。
希望这些点帮助.......
*除问题中所述外,没有其他metod显示。 InitializeComponents在两个窗口的构造函数中都是独一无二的。 – vidstige 2011-01-27 13:48:13
我还处于空白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中设置一个断点,看看会发生什么 - 仔细注意调用堆栈。
祝你好运!
研究这一点,我发现这个奇特的博客条目描述了类似的问题。
事实证明它可能是一个64位处理器体系结构的问题。谁会猜到?!这也许可以解释为什么有些人不能重现这个问题我的简单例子。我试图在“任何CPU”,x64和x86中编译我的例子,但无济于事。在x64上,整个事件实际上已经彻底崩溃,并且出现了一个Windows崩溃对话框。
所以我想这是没有在32位机器上验证它的答案。
总之,异常不能在64位操作系统上传播,因为有用户和内核模式之间的转换。
@ midspace答案中IntPtr.Size的测试不足,因为在x64操作系统上运行的x86进程(您需要使用Environment.Is64BitOperatingSystem
而不是.NET 4及更高版本)时,IntPtr.Size将等于4。
现在的解决方案:使用另一个事件,如ContentRendered
,它在Loaded
之后调用,或者将您的代码放入窗口构造器中。
永远不要在Winforms中使用Loaded
(或OnLoad
),因为如果在那里有异常,你不知道会发生什么。
看一看也是在这样的回答:https://*.com/a/4934010/200443
我试图重现您的情况,但没有成功。例外情况通常会被捕获。 我想,你已经简化了代码,但看起来主要点在细节。提供他们,我会尽力帮助。 – 2011-01-26 17:20:28
感谢您试图重现。我从一个非常简单的例子中转载了这个问题,从我发布的源代码的位置开始。我使用VS2010。我将编辑我的问题并添加一些相关信息以进行复制。 – vidstige 2011-01-27 07:58:24