WPF异常处理详解

news2024/11/20 14:34:31

总目录


文章目录

  • 总目录
  • 一、WPF异常
    • 1 未捕获异常
    • 2 模拟未捕获异常场景
  • 二、处理未捕获异常
    • 1 DispatcherUnhandledException 异常捕获
    • 2 UnhandledException异常捕获
    • 3 UnobservedTaskException异常捕获
    • 4 异常捕获的综合使用
  • 结语


一、WPF异常

1 未捕获异常

正常情况下,开发过程中都会使用try…catch在可能会出现异常的地方去捕获和处理异常。然而实际上开发过程中,由于开发疏忽和一些未知原因,程序中会存在未被处理的异常,当程序运行到此,可能会导致程序崩溃的情况,这样会大大的降低用户的使用体验。对于这种未发现未处理的异常,称之为未捕获异常(UnhandledException)。

2 模拟未捕获异常场景

下面的案例中,就是模拟一个未捕获的异常场景,点击按钮,抛出异常,不使用try…catch 捕获处理。

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            throw new Exception("一个异常!");
        }

在这里插入图片描述
这种由于未捕获异常导致的程序崩溃,从而影响使用者的正常操作,是令人很不友好和反感的。此类异常如果需要追溯就必须去查看Windows的事件日志
在这里插入图片描述

二、处理未捕获异常

我们虽然不能完全杜绝未捕获异常的产生,但是当其出现的时候,我们应当予以处理,做到尽量不影响使用者的操作。

在WPF应用程序中,各类未处理异常及其处理方式如下:

异常种类处理方式案例说明
UI线程抛的异常使用Application.Current.DispatcherUnhandledException 事件处理例如点击了用户界面上面的某个控件,然后执行某行代码的时候,遇到了异常;
非UI线程抛的异常使用AppDomain.CurrentDomain.UnhandledException事件处理例如在一个多线程的程序里面,工作线程的代码遇到了异常。
Task线程抛的异常使用TaskScheduler.UnobservedTaskException事件处理例如在一个多线程的程序里面,工作线程的代码遇到了异常。

1 DispatcherUnhandledException 异常捕获

  • DispatcherUnhandledException 用于捕获UI线程的异常,对于多线程Thread 和Task 异常不会捕获。
  • 该事件中可以通过设置 e.Handle=true ,表明该异常已被处理,不会造成程序崩溃和退出

具体验证代码如下:
在这里插入图片描述
上面测试结果:

  • UI线程异常【可以捕获】,通过e.Handle处理,应用程序不会发生崩溃或退出情况
  • Thread多线程异常【无法捕获】,会造成应用程序崩溃或退出
  • Task多线程异常【无法捕获】,但不会造成程序崩溃或退出

2 UnhandledException异常捕获

  • UnhandledException 用于捕获应用程序所有的异常
  • 该事件只管捕获,没有什么e.Handle的设置去处理异常
  • 若想应用程序捕获到异常后不退出或崩溃需要配合legacyUnhandledExceptionPolicy 配置设置实现(作用类似于e.Handle=true)

如何配置legacyUnhandledExceptionPolicy 呢?只需要在 app.config 文件的 <runtime> 节点中添加如下代码:

<legacyUnhandledExceptionPolicy enabled="1"/>  

具体使用案例如下所示:
在这里插入图片描述
上面测试结果:

  • UI线程异常【可以捕获】,但是应用程序仍会发生崩溃或退出情况
  • Thread多线程异常【可以捕获】,应用程序不会崩溃或退出
  • Task多线程异常【无法捕获】,也不会造成程序崩溃或退出

3 UnobservedTaskException异常捕获

  • UnobservedTaskException 专用于捕获Task 多线程异常
    在这里插入图片描述
    上面测试结果:
  • UI线程异常【无法捕获】,应用程序发生崩溃或退出
  • Thread多线程异常【无法捕获】,应用程序会崩溃或退出
  • Task多线程异常【可以捕获】,由于Task多线程的异常本身也不会让应用程序崩溃或退出,因此我们只需在捕获的事件内处理异常即可

UnobservedTaskException 事件执行的时机?

通过上面的案例中,我们发现在Task中发生异常了以后,并不会马上执行UnobservedTaskException 事件内的代码,而是会等一会儿才执行? 这是因为Task异常只有在垃圾回收的时候,才会推送到该事件内进行处理。

4 异常捕获的综合使用

  • 在xaml中
    <StackPanel>
        <Button Content="测试UI线程异常" Width="300" Height="50" Click="Button_Click" Margin="10"></Button>
        <Button Content="测试Thread线程异常" Width="300" Height="50" Click="Button_Click_1" Margin="10"></Button>
        <Button Content="测试Task线程异常" Width="300" Height="50" Click="Button_Click_2" Margin="10"></Button>
    </StackPanel>
  • 在代码中
        private void Button_Click(object sender, RoutedEventArgs e)
        {
            throw new Exception("UI线程异常[01]!");
        }

        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            new Thread(new ThreadStart(()=> 
            {
                throw new Exception("Thread多线程异常[02]");
            })).Start();
        }

        private void Button_Click_2(object sender, RoutedEventArgs e)
        {
            Task.Run(()=> 
            {
                throw new Exception("Task多线程异常[03]");                
            });
        }
  • 在App.xaml.cs的代码中
    public partial class App : Application
    {
        public App()
        {
            //当应用程序引发但未处理异常时出现,UI线程的异常,无法捕获多线程异常
            Application.Current.DispatcherUnhandledException += Current_DispatcherUnhandledException;
            
            //当某个异常未被捕获时出现
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            //未被观察到的Task多线程异常
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
        }

        private void Current_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            e.Handled = true;
            MessageBox.Show($"Current_DispatcherUnhandledException:" + e.Exception.Message);
        }
        private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            MessageBox.Show($"CurrentDomain_UnhandledException:" + (e.ExceptionObject as Exception).Message);
        }
        private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            MessageBox.Show($"TaskScheduler_UnobservedTaskException:" + e.Exception.Message);
        }
    }

结语

以上就是本文的内容,希望以上内容可以帮助到您,如文中有不对之处,还请批评指正。


参考资料:
WPF异常处理
TaskScheduler.UnobservedTaskException 事件

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/502190.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《走进对象村5》面向对象的第二大特性——继承

文章目录 &#x1f680;文章导读1.1 为什么需要继承1.2 继承的概念**关于继承有如下三点请记住&#xff1a;**1.4 父类成员访问1.4.1 子类中访问父类成员变量1.4.2 super 关键字1.4.3 子类中访问父类成员方法 1.5 子类构造方法1.6 面试题this 和 super 的区别(重点)1.7 再谈代码…

深度解读绩效管理PDCA循环(含操作指南、案例应用)

绩效管理的PDCA循环是一个重要的管理工具&#xff0c;它由四个步骤组成&#xff1a;绩效计划&#xff08;Plan&#xff09;、绩效执行&#xff08;Do&#xff09;、绩效评估&#xff08;Check&#xff09;和结果应用&#xff08;Action&#xff09;。这个循环可以帮助组织不断地…

【红黑树】到底是什么,它有哪些基本操作,它的用处是什么,代码如何实现

红黑树是一种自平衡二叉查找树&#xff0c;具有良好的时间复杂度和空间复杂度&#xff0c;被广泛应用于计算机科学领域中&#xff0c;如操作系统、编译器、数据库等。在实际应用中&#xff0c;红黑树主要用于实现高效的查找和排序&#xff0c;如 Linux 内核中的进程调度和空闲内…

VRIK+Unity XR Interaction Toolkit 配置 VR 全身模型(下):实现腿部行走动画

在上一篇教程&#xff1a;VRIKUnity XR Interaction Toolkit 配置 VR 全身模型&#xff08;上&#xff09;&#xff1a;实现上半身的追踪&#xff08;附带VRM模型导入Unity方法和手腕扭曲的解决方法&#xff09;当中&#xff0c;我们通过配置VRIK Unity XR Interaction Toolki…

WiFi(Wireless Fidelity)基础(一)

目录 一、基本介绍&#xff08;Introduction&#xff09; 二、进化发展&#xff08;Evolution&#xff09; 三、PHY帧&#xff08;&#xff08;PHY Frame &#xff09; 四、MAC帧&#xff08;MAC Frame &#xff09; 五、协议&#xff08;Protocol&#xff09; 六、安全&#x…

小松鼠踩一踩游戏

文章目录 一、 介绍和知识点九、UnityFacade 门面设计模式二、 声音全局管理器测试音频代码UI全局管理器父类抽象类 BaseManager子类 UIManager 四、 UI按钮的引用父类 BasePanel子类主面板 MainPanel子类 游戏中 GamePanel子类 游戏结果 ResultPanel 角色动画器、控制角色移动…

性能测试如何做?一套完整的性能测试流程,“我“拒绝背锅...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 1、测试准备工作 …

中兴B860AV2.1-T(M)-高安版-当贝纯净桌面线刷固件包

中兴B860AV2.1-T(M)-高安版-当贝纯净桌面线刷固件包-内有教程及短接点 特点&#xff1a; 1、适用于对应型号的电视盒子刷机&#xff1b; 2、开放原厂固件屏蔽的市场安装和u盘安装apk&#xff1b; 3、修改dns&#xff0c;三网通用&#xff1b; 4、大量精简内置的没用的软件…

有序序列中插入一个整数

思路&#xff1a; 将输入的要插入的数m依次和数组中的元素进行比较。 思&#xff1a; 在排好序的数组中&#xff0c;从右往左比较还是从左往右比较&#xff1f; 其实都可以&#xff0c;但是我觉得从右边&#xff08;也就是最大的数&#xff09;依次开始比较&#xff0c;程序比较…

纯前端JS实现文件上传解析渲染页面

AI真的能代替前端吗&#xff1f; 回答&#xff1a;不会完全代替 能用吗&#xff1f;复制到项目中只会报错 爆红 ……他完全不能理解你需要什么JavaScript&#xff08;简称JS&#xff09;是一种轻量级的脚本语言&#xff0c;主要用于在Web页面上添加交互行为。它由三个不同的…

5月跳槽有风险,不跳也有?

今天讲讲跳槽。 说实话跳槽是为了寻求更好的发展&#xff0c;但在跳槽前我们也不能确定下家就是更好的归宿&#xff0c;这就更加需要我们审慎地去对待&#xff0c;不能盲目跳槽。 其次&#xff0c;我们离职和跳槽&#xff0c;其中的原因很大一部分是目前薪资不符合预期。 那…

基于python+opencv的人脸识别打卡(手把手教你)

基于pythonopencv的人脸识别打卡 1 创建环境2 准备工作2.1新建members.csv文件2.2新建face文件夹2.3注意事项 3 源码4 操作步骤 1 创建环境 conda create -n face python3.7 conda activate face pip install opencv-python pip install pillow pip install opencv-contrib-py…

基于Redis中zset实现延时任务

目录 概要 一、实现原理 适用场景 二、准备工作 三、代码实现 四、zset的优缺点 优点 缺点 概要 本文章主要记录的是使用Redis中的zset实现延时任务&#xff0c;在工作中&#xff0c;像这样的的延时任务是不可避免的&#xff0c;举个栗子&#xff1a;买一张火车票&#…

企业如何利用网络趋势做好线上营销?

随着互联网的不断发展&#xff0c;线上营销越来越成为企业营销的重要组成部分。如何利用网络趋势做好线上营销&#xff0c;已经成为各大企业关注的焦点。本文将为大家介绍如何利用网络趋势做好线上营销的方法和技巧。 一、了解网络趋势 了解网络趋势是做好线上营销的关键。网络…

uboot移植Linux-SD驱动代码解析

一、uboot与linux驱动 1.1、uboot本身是裸机程序 (1)狭义的驱动概念是指&#xff1a;操作系统中用来具体操控硬件的代码叫驱动 广义的驱动概念是指&#xff1a;凡是操控硬件的代码都叫驱动 (2)裸机程序中是直接使用寄存器的物理地址来操控硬件的&#xff0c;操作系统中必须通…

最新版千帆直播网站系统PHP完整版源码(PC+WAP在线观看视频)附安装教程

最新版千帆直播网站PHP完整版源码&#xff0c;PCWAP在线观看视频直播系统 安装方法&#xff1a; 1、导入数据库文件 zhibo.sql 2、修改数据库配置文件 有多处包含UC配置; 根目录&#xff1a;config.inc.php – config.php 其他路径&#xff1a; Conf/config.php Admin/C…

JVM(三):JVM命令与参数

JVM命令与参数 文章目录 JVM命令与参数JVM参数标准参数-X 参数-XX参数其他参数说明常用参数的意义 常用命令jpsjinfojstatjstackjmap 常用工具jconsolejvisualvm内存分析工具 MATGC日志分析工具内存分析工具 MATGC日志分析工具 经过前面的各种分析学习&#xff0c;我们知道了关…

淦,服务器被人传了后门木马。。。

「作者简介」&#xff1a;CSDN top100、阿里云博客专家、华为云享专家、网络安全领域优质创作者 「推荐专栏」&#xff1a;对网络安全感兴趣的小伙伴可以关注专栏《网络安全入门到精通》 今天很暴躁&#xff0c;因为睡眠被打扰了。 一个朋友大半夜打我电话&#xff0c;说她云服…

ThingsBoard 接入摄像头方案

0、上图 废话不多说,先给大家来个效果图: 1、概述 最近,我在群里看到有很多兄弟向我咨询摄像头接入到tb的方案,这个就是找对人了,后续我会截图我当初做的东西,其实这个很简单,而且我这种方法是最好的,下面给大家一一道来。 我总结了下面几种情况,其实关键在于摄像头…

QML画布元素

在早些时候的Qt4中加入QML时&#xff0c;一些开发者讨论如何在QtQuick中绘制一个圆形。类似圆形的问题&#xff0c;一些开发者也对于其它的形状的支持进行了讨论。在QtQuick中没有圆形&#xff0c;只有矩形。在Qt4中&#xff0c;如果你需要一个除了矩形外的形状&#xff0c;你需…