C# eventhandler中引发的WPF异常是否被吞没?

C# eventhandler中引发的WPF异常是否被吞没?,c#,.net,wpf,xaml,exception-handling,C#,.net,Wpf,Xaml,Exception Handling,当我在eventhandler中抛出异常时,是否不调用exceptionhandler 一个简单示例的示例代码,以以下内容开始: App.xaml <Application x:Class="WpfApplication1.App" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/

当我在eventhandler中抛出异常时,是否不调用exceptionhandler

一个简单示例的示例代码,以以下内容开始:

App.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>
<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>
main window.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>
<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>
我已经看过了,但强制32位或64位,甚至“任何CPU”都不起作用。此外,在设置任何(!)处理程序时,在事件中引发异常时,它们都不会被调用。也没用

我正在运行VS2012(在Win8上,x64),该项目使用的是.Net Framework 4.5)。我错过了什么?我疯了吗

为清楚起见:我希望显示一个messagebox(当我单击
按钮时会显示),或者实际上是调用
App\u dispatchernandledexception
方法。但是当我单击
按钮b
时,该方法没有被调用(因此消息框没有显示)。
ButtonA
ButtonB
之间的唯一区别在于“
A
”中的异常不在eventhandler中,而“
B
中的异常不在eventhandler中。当然,我会在
OpenFileDialog
中选择一个文件,然后单击“打开”将其选中。调试器启动并指出抛出了“不工作!?!?”异常,然后我继续执行,没有显示messagebox

另外:我是WPF的新手,这可能是问题的一部分

编辑1

以下两个zipfiles演示了确切的问题,以供参考:

  • (10Kb)
  • (10Kb)
  • 在我的计算机上,对于上述两个项目,ButtonA会显示一个messagebox,ButtonB(在选择文件后)不会。曾经即使在启用或不启用“调试非托管代码”的情况下也不行

    编辑2

    因此,我在另一台机器上运行了相同的代码,并发现:在另一台机器上,调试器显示:

    注意
    异常跨越了本机/托管边界
    标题。当我尝试恢复执行(继续)时,异常会不断弹出。当调试器启动时,我的计算机显示:

    …然后,当我恢复执行时,异常消失在某种黑洞中;主窗体再次显示,但什么也没有发生

    这应该与此设置有关:

    但是,即使重新启动VS2012和(以及项目中的bin/obj目录),打开/关闭此选项也无济于事


    所以。。。我现在知道,这个例外确实与托管和非托管之间的跨边界有关。现在,我只需要找出如何解决这个问题,这样我就可以在
    文件OK
    事件中抛出异常(这样,最终我的组件也可以抛出异常)。

    如果像这样连接它,您将看到它正在被处理
    仍然不知道为什么它会逃避App_dispatchernhandledexception

    using System.ComponentModel;
    //using Microsoft.Win32;
    
    
    namespace UncaughtExceptionHandler
    {
        /// <summary>
        /// Interaction logic for MainWindow.xaml
        /// </summary>
        public partial class MainWindow : Window
        {
            public MainWindow()
            {
                //AppDomain currentDomain = AppDomain.CurrentDomain;
                //currentDomain.UnhandledException += new UnhandledExceptionEventHandler(MyHandler);
                InitializeComponent();
            }
            private void ButtonA_Click(object sender, RoutedEventArgs e)
            {
                throw new Exception("WTFA!?!?");
            }
            private void ButtonB_Click(object sender, RoutedEventArgs e)
            {
                System.Windows.Forms.OpenFileDialog ofd = new System.Windows.Forms.OpenFileDialog();
                ofd.FileOk += MyCanelEventHandler;
                //ofd.FileOk += (s, ce) =>
                //{
                //    //MessageBox.Show("Throwikng Exception WTF2!?!?");
                //    throw new Exception("WTF2!?!?");
                //};
                ofd.ShowDialog();
            }
            static void MyCanelEventHandler(Object sender, CancelEventArgs e)
            {
                MessageBox.Show("MyCanelEventHandler");
                throw new Exception("WTFCEH!?!?");
            }
        }
    }
    
    使用System.ComponentModel;
    //使用Microsoft.Win32;
    命名空间UncaughtExceptionHandler
    {
    /// 
    ///MainWindow.xaml的交互逻辑
    /// 
    公共部分类主窗口:窗口
    {
    公共主窗口()
    {
    //AppDomain currentDomain=AppDomain.currentDomain;
    //currentDomain.UnhandledException+=新的UnhandledExceptionEventHandler(MyHandler);
    初始化组件();
    }
    私有无效按钮单击(对象发送者,路由目标)
    {
    抛出新异常(“WTFA!?!?”);
    }
    私有无效按钮b\u单击(对象发送者,路由目标)
    {
    System.Windows.Forms.OpenFileDialog ofd=新建System.Windows.Forms.OpenFileDialog();
    ofd.FileOk+=MyCanelEventHandler;
    //ofd.FileOk+=(s,ce)=>
    //{
    ////MessageBox.Show(“Throwikng异常WTF2!?!”;
    //抛出新异常(“WTF2!?!?”;
    //};
    ShowDialog();
    }
    静态void MyCanelEventHandler(对象发送方,CancelEventArgs e)
    {
    MessageBox.Show(“MyCanelEventHandler”);
    抛出新异常(“WTFCEH!?!?”;
    }
    }
    }
    
    调试101是获取一个调用堆栈。
    我在10分钟内得到了一个呼叫堆栈

    OP做出了三个无效的假设,即使经过长时间的讨论也无法理解

  • 异常正在被吞没
    它并没有被吞下,只是通过了他未捕获的异常处理程序 我的代码演示了这一点,但OP没有遵循
  • 解决方案没有无人操作的代码
    再次出错OpenFileDialog是非托管代码
  • 正在从托管代码引发异常
    又错了
    从非托管代码的回调引发异常
  • 回调中的第一行
    Degbug 101正在获取一个调用堆栈

    UncaughtExceptionHandler.exe!UncaughtExceptionHandler.MainWindow.MyCanelEventHandler(对象发送器,System.ComponentModel.CancelEventArgs e)第55行C# comdlg32.dll!CFileOpenSave::\u NotifyFileOkChangeCallback()+0x18字节 comctl32.dll_DPA_EnumCallback@12()+0x20字节
    comdlg32.dll!CFileOpenSave::\u NotifyFileOk()+0x3d字节
    comdlg32.dll!CFileOpenSave::_CleanupDialog()+0x46c2字节
    comdlg32.dll!CFileOpenSave::_HandleOkAndClose()+0x3a字节
    comdlg32.dll!CFileOpenSave::\u OnCommandMessage()+0xf432字节 comdlg32.dll!CFileOpenSave::s_OpenSaveDlgProc()+0x1f42字节 user32.dll_InternalCallWinProc@20()+0x23字节
    user32.dll_UserCallDlgProcCheckWow@32()+0xa9字节
    user32.dll_DefDlgProcWorker@20()+0x7f字节 user32.dll_DefDlgProcW@16()+0x22字节


    好的,我解决了我的问题

    谷歌搜索、冲浪等等,我最终还是和他分手了。现在我清楚了FileOk事件是如何在另一个dispatcher上处理的,因此解决方案很简单:

    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();
    }
    
    这样可以确保将异常传递给正确的dispa