【问题标题】:Where should AppDomain.UnhandledException be subscribed to?AppDomain.UnhandledException 应该在哪里订阅?
【发布时间】:2015-05-19 11:59:22
【问题描述】:

建议的副本是关于DispatcherUnhandledException,而不是AppDomain.CurrentDomain.UnhandledException

原创

AppDomain.UnhandledException 应该在哪里订阅? MSDN 上的示例只是在 Main 中显示它,这就是我在 Winforms 中所做的:我在 Program.Main 中订阅它:

AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

但我在 WPF 中找不到合适的位置,其中隐藏了 Main。我已经搜索过,但主要发现了是否订阅它的讨论,假设读者现在会在哪里。

【问题讨论】:

标签: c# .net wpf


【解决方案1】:

假设您在 Visual Studio 中使用默认模板创建了项目,您应该有一个名为 app.xaml 的文件,其下还有另一个名为 app.xaml.cs 的文件。

App 类中,您可以将它添加到OnStartup 的开头(连同Dispatcher.UnhandledException):

protected override void OnStartup(StartupEventArgs e)
{
    // don't forget to call base implementation
    base.OnStartup(e);

    Dispatcher.UnhandledException += Dispatcher_UnhandledException;
    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}

实际上,Dispatcher.UnhandledException 在大多数情况下应该足够了。这意味着您可以完全跳过使用AppDomain.CurrentDomain.UnhandledException。也注册到AppDomain.CurrentDomain.UnhandledException 的唯一原因是在主 UI 线程以外的线程中引发异常。但我认为在它们各自的线程中实际捕获这些异常是更好的做法。

【讨论】:

  • 谢谢,但我也在编辑它。我会做不同的事情。
  • 没问题。来吧:)
  • 我更喜欢在调用基本实现之前设置回调。这是一个好习惯吗?
  • 我会说调用 WPF 基础代码比你自己的调用更重要。在这种情况下,我不会这样做,或者使用try... catch 来确保它被调用。
  • 很公平。同样在那种特殊情况下,我认为这并不重要:我看不出注册这两个代表会出现什么问题。
【解决方案2】:

WPF 中的 Main() 入口点是从 App.xaml 源文件自动生成的。您必须订阅事件的最早机会是在 App.xaml.cs 中 App 类的构造函数中:

public partial class App : Application {
    public App() {
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    }

    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
        // etc...
    }
}

但这并不是“完美的”,您无法检测到 Application 类的字段初始化程序中的任何故障。以及您在 Application 类中使用的类型的任何 JIT 编译失败,缺少程序集或版本控制问题是通常的麻烦制造者。

为避免错过这些,您需要放弃自动生成的代码并编写自己的 Main() 方法。假设您没有大量修改 app.xaml 文件。从项目中删除该文件并添加一个新类,我建议 Program.cs :) 并使其看起来类似于:

using System;
using System.Runtime.CompilerServices;
using System.Windows;

namespace WpfApplication1 {
    class Program {
        [STAThread]
        public static void Main(string[] args) {
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
            Start();
        }

        [MethodImpl(MethodImplOptions.NoInlining)]
        private static void Start() {
            var app = new App();
            app.Run(new MainWindow());
        }

        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e) {
            // etc..
        }
    }

    public class App : Application {
        // etc..
    }
}

【讨论】:

    【解决方案3】:

    您可以在您的App.xaml.cs 中覆盖OnStartup 方法,这是您最接近Main 方法的方法(如果您愿意,也可以使用App 构造函数)

    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            base.OnStartup(e);
    
            // register the event handler here
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        }
    }
    

    请注意,这需要您省略 StartupUri 并自己打开 Window

    【讨论】:

    猜你喜欢
    • 2023-03-27
    • 2020-07-02
    • 2017-09-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-04-06
    • 2016-03-26
    相关资源
    最近更新 更多