Rob*_*III 4 .net c# wpf xaml exception-handling
当我在事件处理程序中抛出异常时,异常处理程序没有被调用?
从以下开始的精简示例的示例代码:
应用程序.xaml
<Application x:Class="WpfApplication1.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
StartupUri="MainWindow.xaml"
DispatcherUnhandledException="App_DispatcherUnhandledException" >
<Application.Resources/>
</Application>
Run Code Online (Sandbox Code Playgroud)
应用程序.xaml.cs
using System.Windows;
using System.Windows.Threading;
namespace WpfApplication1
{
public partial class App : Application
{
//This method is called when ButtonA is clicked, but not when ButtonB is
//clicked (and a (random) file is selected ofcourse).
void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
{
MessageBox.Show(e.Exception.Message, "An exception occurred", MessageBoxButton.OK, MessageBoxImage.Error);
e.Handled = true;
}
}
}
Run Code Online (Sandbox Code Playgroud)
主窗口.xaml
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Button Content="Button A" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="75" Click="ButtonA_Click"/>
<Button Content="Button B" HorizontalAlignment="Left" Margin="90,10,0,0" VerticalAlignment="Top" Width="75" Click="ButtonB_Click"/>
</Grid>
</Window>
Run Code Online (Sandbox Code Playgroud)
主窗口.xaml.cs
using Microsoft.Win32;
using System;
using System.Windows;
namespace WpfApplication1
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void ButtonA_Click(object sender, RoutedEventArgs e)
{
throw new Exception("Works!");
}
private void ButtonB_Click(object sender, RoutedEventArgs e)
{
var ofd = new OpenFileDialog();
ofd.FileOk += (s, ce) => {
throw new Exception("Does not work!?!?");
};
ofd.ShowDialog();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我已经看过这个问题和这个问题,但是强制使用 32 位或 64 位甚至“任何 CPU”都不起作用。此外,当设置这四个(!) 处理程序中的任何一个时,当在事件中抛出异常时,它们都不会被调用。同时此文章没有帮助。
我正在运行 VS2012(在 Win8、x64 上),该项目使用 .Net Framework 4.5)。我错过了什么?我要疯了吗?
为清楚起见:我希望显示一个消息框(当我单击时它会显示ButtonA),或者,实际上,完全App_DispatcherUnhandledException调用该方法。但是当我单击 时不会调用该方法(因此不显示消息框)ButtonB。ButtonA和之间的唯一区别ButtonB是“ A”中的异常不在事件处理程序中,而“ B”中的异常在。而且,当然,我确实在 中选择了一个文件,OpenFileDialog然后单击“打开”来选择它。调试器启动并指出“不起作用!?!? ”异常被抛出,然后我继续执行并且没有显示消息框。
另外:我对 WPF 还很陌生,这可能是问题的一部分 
编辑 1
作为参考,这里有两个 zipfile 演示了确切的问题:
在我的计算机上,对于上述两个项目,ButtonA 会导致显示一个消息框,而 ButtonB(选择文件后)不会。曾经。甚至没有打开“调试非托管代码”。
编辑 2
所以,我在另一台机器上运行了相同的代码并发现了这一点:在另一台机器上,调试器显示:

注意Exception crossed a native/managed boundary标题。当我尝试恢复执行(继续)时,异常不断弹出。我的机器,当调试器启动时,显示:

...然后,当我恢复执行时,异常消失在某种黑洞中;主窗体再次显示,没有任何反应。
这应该与此设置有关:

但是,即使重新启动 VS2012 并删除临时文件(以及项目中的 bin/obj 目录)、恢复默认值等,打开/关闭此选项也无济于事。
所以...我现在知道异常确实与托管和非托管之间的跨界有关。现在我只需要弄清楚如何解决这个问题,以便我可以在FileOk事件中抛出异常(这样,最终,我的组件也可以在那里抛出)。
好的,所以我解决了我的问题。
谷歌搜索,冲浪等。我最终在这里和这里结束。现在我很清楚 FileOk 事件是如何在另一个调度程序上处理的,因此解决方案很简单:
private void ButtonB_Click(object sender, RoutedEventArgs e)
{
var ofd = new OpenFileDialog();
ofd.FileOk += (s, ce) => {
this.Dispatcher.BeginInvoke((Action)(() =>
{
//We can throw:
throw new Exception("Yay! This exception is now caught by the UnhandledException handler!");
//or, alternatively, our component can do work that possibly throws:
Component.DoFoo();
}));
};
ofd.ShowDialog();
}
Run Code Online (Sandbox Code Playgroud)
这确保异常被传递到正确的调度程序并在那里处理。App_DispatcherUnhandledException然后正确调用该方法,我们可以从那里获取它。
| 归档时间: |
|
| 查看次数: |
3215 次 |
| 最近记录: |