Java自学者论坛

 找回密码
 立即注册

手机号码,快捷登录

恭喜Java自学者论坛(https://www.javazxz.com)已经为数万Java学习者服务超过8年了!积累会员资料超过10000G+
成为本站VIP会员,下载本站10000G+会员资源,会员资料板块,购买链接:点击进入购买VIP会员

JAVA高级面试进阶训练营视频教程

Java架构师系统进阶VIP课程

分布式高可用全栈开发微服务教程Go语言视频零基础入门到精通Java架构师3期(课件+源码)
Java开发全终端实战租房项目视频教程SpringBoot2.X入门到高级使用教程大数据培训第六期全套视频教程深度学习(CNN RNN GAN)算法原理Java亿级流量电商系统视频教程
互联网架构师视频教程年薪50万Spark2.0从入门到精通年薪50万!人工智能学习路线教程年薪50万大数据入门到精通学习路线年薪50万机器学习入门到精通教程
仿小米商城类app和小程序视频教程深度学习数据分析基础到实战最新黑马javaEE2.1就业课程从 0到JVM实战高手教程MySQL入门到精通教程
查看: 539|回复: 0

WPF 程序 处理未捕获异常,和程序莫名终止说拜拜

[复制链接]
  • TA的每日心情
    奋斗
    6 小时前
  • 签到天数: 781 天

    [LV.10]以坛为家III

    2048

    主题

    2106

    帖子

    72万

    积分

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    720164
    发表于 2021-6-8 10:02:54 | 显示全部楼层 |阅读模式

    百密一疏的Bug很难避免,没有谁能保证,我的程序永远 0 BUG;

     

    突然接手一个很庞大的项目,在项目运行期间会莫名异常结束,异常极难重现,还找不出BUG代码,代码太多了。

    这个时候就需要把程序中发生的BUG记录下来,知道哪里BUG了,才好下次更新解决。

    把所有代码全部加 try catch ?  那就怀孕了,真的搞大了。

     

    未捕获的异常处理:

    一:C# 在 Application 类中提供了 DispatcherUnhandledException 事件,用于处理UI线程上未捕获的异常

    App.Current.DispatcherUnhandledException += App_DispatcherUnhandledException;
    void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
    {
    //e.Exception 发生的异常
    //e.Handled 是否已处理异常事件
    }

    但是 DispatcherUnhandledException 捕获不了 非UI线程上发生的异常

     

    二:C# 在 AppDomain 类中提供了 UnhandledException 事件,用于捕获应用程序域中发生的异常

    AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
    
    void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        MessageBox.Show("Unhandle");
    //MessageBox.Show((e.ExceptionObject == null ? "Null" : e.ExceptionObject.GetType().Name),
        //    "CurrentDomain_UnhandledException:");
    }

    这样就能捕获应用程序域中发生的异常,当然,包括UI线程和非UI线程异常,如果你有创建应用程序域的需求,创建完成,再绑定下事件即可。

    但是AppDomain.UnhandledException 事件没有提供 终止异常,也就是说,异常发生了,你没捕获,这里通知一下,但是该程序结束还得结束。

     

    在这里要特别提到官方封装的 Delegate.BeginInvoke();

    "已知:"在异步函数中发生了异常并且没处理:

    "求解:"

    1.没调用 Delegate.EndInvoke() 函数:

        终止执行。 程序不会挂掉,异常丢弃。这是种很隐蔽的BUG,很难发现。

        AppDomain.UnhandledException 事件不会通知发生了异常,这里要特别注意。

    public void Hello()
    {
        World();
        Load();
    }
    
    public void World()
    {
    throw new Exception();
    }
    public void Load() { MessageBox.Show("Suc"); } var action = new Action(Hello); action.BeginInvoke(null, null);

    像这种示例,如果在World() 方法中发生了异常,线程会立即终止,Load() 函数就不会执行,程序也不会终止。

    一个函数没有执行,也许就会导致很严重的异常,还很难发现。

     

    2.调用了 Delegate.EndInvoke() 函数:

        异常抛出, 程序挂掉。

        AppDomain.UnhandledException 事件会通知发生了异常

     

    这里也许会有个需求,如果我想处理 AppDomain.UnhandledException 事件中的异常怎么办?程序挂了太恶心了。

    我们来继续扩展这个框架

    解决在非UI线程中访问UI 异常的小方法

    /// <summary>
    /// 委托 扩展类
    /// </summary>
    public static class DelegateExtension
    {
    /// <summary> /// 可以被捕获异常的异步调用 /// </summary> /// <param name="dele"></param> public static void UnsafeBeginInvoke(this Delegate dele) { var action = new Action(() => { dele.DynamicInvoke(); }); action.BeginInvoke(new AsyncCallback((ar) => { try { action.EndInvoke(ar); } catch (Exception ex) { App.Current.Dispatcher.BeginInvoke(new Action(() => { throw ex; })); } }), null); } }

    有点不伦不类哈,厄。把异常推送到UI线程上抛出,让Application.DispatcherUnhandledException 事件处理

     

    其它:C# 在 TaskScheduler 类中提供了 UnobservedTaskException 事件,用于捕获 Task 异步异常.

    哎...今天够累的,签到来了1...
    回复

    使用道具 举报

    您需要登录后才可以回帖 登录 | 立即注册

    本版积分规则

    QQ|手机版|小黑屋|Java自学者论坛 ( 声明:本站文章及资料整理自互联网,用于Java自学者交流学习使用,对资料版权不负任何法律责任,若有侵权请及时联系客服屏蔽删除 )

    GMT+8, 2024-8-21 21:47 , Processed in 0.103782 second(s), 29 queries .

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表