首页 > 其他分享 >WPF的三个全局异常捕捉

WPF的三个全局异常捕捉

时间:2024-11-27 17:34:30浏览次数:6  
标签:Task 捕获 应用程序 线程 UI 捕捉 WPF 异常 全局

1. UI线程未捕获异常处理事件(DispatcherUnhandledException)

  • 作用和触发时机
    • 在WPF应用中,UI线程负责处理界面的交互、渲染等诸多操作。当在UI线程上发生了异常,并且这个异常没有被代码中常规的 try-catch 块等方式捕获处理时,就会触发 DispatcherUnhandledException 事件。例如,在某个按钮的点击事件处理程序中(该处理程序运行在UI线程上),如果执行了一段可能出错的代码,像访问一个空引用的对象属性或者进行非法的类型转换等操作且没有提前捕获异常,那么这个事件就会被触发。
  • 使用方式及示例代码
public partial class App : Application
{
    private void App_DispatcherUnhandledException(object sender, DispatcherUnhandledExceptionEventArgs e)
    {
        // 可以在这里记录异常信息,比如写入日志文件
        Console.WriteLine($"UI线程发生未捕获异常: {e.Exception.Message}");
        // 设置为已处理,避免程序默认的异常弹出对话框导致程序终止(可根据需求决定是否这样做)
        e.Handled = true; 
    }
}

在上述示例中,定义在 App 类(通常是WPF应用的启动类,继承自 Application)里的 App_DispatcherUnhandledException 方法就是用来处理UI线程未捕获异常的。可以根据实际需求在这个方法中进行更复杂的操作,比如弹出一个友好的提示框告知用户出现了错误、将详细异常信息发送到远程服务器用于分析等,最后通过设置 e.Handledtrue 来告知WPF框架这个异常已经被“处理”了,从而避免应用程序直接崩溃并弹出默认的异常对话框。

2. Task线程内未捕获异常处理事件(TaskScheduler_UnobservedTaskException)

  • 作用和触发时机
    • 当在使用 Task 来进行异步操作时(例如通过 Task.Run 启动一个在后台线程执行的任务等),如果在这个 Task 所代表的异步操作中发生了异常,并且这个异常没有被 Task 内部的 try-catch 等机制捕获,同时在后续代码中也没有主动去观察(处理)这个异常(例如没有调用 TaskWaitResult 等会引发异常传播的方法,或者没有注册异常处理回调等),就会触发 TaskScheduler.UnobservedTaskException 事件。比如在一个异步下载文件的 Task 中,如果因为网络问题或者文件权限问题导致出现异常,且没有在 Task 本身的执行逻辑里处理,那么就可能触发该事件。
  • 使用方式及示例代码
public partial class App : Application
{
    private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
    {
        // 记录异常相关信息
        Console.WriteLine($"Task线程发生未捕获异常,异常详情如下:");
        foreach (var innerException in e.Exception.InnerExceptions)
        {
            Console.WriteLine(innerException.Message);
        }
        // 设置为已观察,避免CLR(公共语言运行时)终止应用程序(根据实际情况决定是否这样做)
        e.SetObserved();
    }
}

这里的 TaskScheduler_UnobservedTaskException 方法用于处理 Task 线程中的未捕获异常情况。在实际应用中,可以把异常信息发送给开发者用于分析异步任务失败的原因,同时通过 e.SetObserved() 告知运行时这个异常已经被关注了,防止因为未处理的异常积累等情况导致整个应用程序意外终止,因为默认情况下,未观察到的 Task 异常可能会使CLR采取一些比较强硬的措施来终止应用的运行。

3. 非UI线程未捕获异常处理事件(CurrentDomain_UnhandledException)

  • 作用和触发时机
    • 对于那些既不是UI线程也不是通过 Task 等特定异步机制管理的普通线程(比如手动通过 Thread 类创建并启动的线程等),当在这些线程上发生了异常且没有被捕获时,就会触发 AppDomain.CurrentDomain.UnhandledException 事件。例如,创建一个新线程去执行一个长时间运行的数据处理任务,如果在这个数据处理过程中出现了诸如数组越界、内存不足等异常且没有提前处理,就会引发该事件。
  • 使用方式及示例代码
public partial class App : Application
{
    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        // 输出异常信息
        Console.WriteLine($"非UI线程发生未捕获异常,异常消息: {((Exception)e.ExceptionObject).Message}");
        // 这里的IsTerminating属性可以判断是否会导致应用程序终止
        if (e.IsTerminating)
        {
            Console.WriteLine("该未捕获异常将导致应用程序终止");
        }
    }
}

CurrentDomain_UnhandledException 方法负责应对非UI线程的未捕获异常情况。可以利用这个机会在应用程序彻底崩溃前做一些重要的事情,比如保存当前应用的一些关键状态数据到本地磁盘等,因为一旦触发这个事件且 IsTerminating 属性为 true (通常情况下是这样,除非应用有特殊的宿主环境等可以避免终止),意味着应用程序即将因为这个未处理的异常而结束运行了。

合理利用这三种异常处理事件机制,可以增强WPF应用程序的健壮性,让应用在面对各种可能出现的异常情况时能够有更好的应对策略,尽可能避免因为异常导致的程序意外崩溃以及数据丢失等问题。

标签:Task,捕获,应用程序,线程,UI,捕捉,WPF,异常,全局
From: https://www.cnblogs.com/ziyuhaokun/p/18572731

相关文章

  • 【Springboot】全局异常可以捕获但无法返回给前端
    场景创建全局自定义异常处理类@Slf4j@ControllerAdvicepublicclassGlobalExceptionHandler{/***全局异常处理,统一返回rtnCode=2**@parame*@return*/@ExceptionHandler(Exception.class)publicObjecthandleException(......
  • 一款基于Fluent设计风格、现代化的WPF UI控件库
    前言今天大姚给大家分享一款基于Fluent设计风格、开源(MITLicense)、现代化的WPFUI控件库,它提供直观的设计、主题、导航和全新的沉浸式控件,全部都是原生且无缝地集成在一起:WPFUI。WPF介绍WPF是一个强大的桌面应用程序框架,用于构建具有丰富用户界面的Windows应用。它提......
  • WPF Datagrid AutoScroll via behavior
    publicclassDataGridAutoScrollBehavior:Behavior<DataGrid>{protectedoverridevoidOnAttached(){base.OnAttached();AssociatedObject.SelectionChanged+=AssociatedObject_SelectionChanged;}privatevoidAssociated......
  • WPF Datagrid DataGridTemplateColumn DataTemplate UserControl MVVM
    //uercontrol<UserControlx:Class="WpfApp47.ImgTbk"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:mc=&......
  • WPF 粉笔绘制
    在做白板书写的时候,会有各种笔的绘制,比如书写笔、马克笔、演示笔等等。粉笔的功能需求也是很有必要的。上网搜了一圈,几乎没有绘制粉笔的。有的是毛笔、楷体等绘制的如下博客:wpfinkcanvascustomink毛笔效果_wpfinkcanvas笔锋-CSDN博客【WPF】InkCanvas书写毛笔效果-CSD......
  • ULID(Universally Unique Lexicographically Sortable Identifier,通用唯一词典分类标识
    ULID(UniversallyUniqueLexicographicallySortableIdentifier,通用唯一词典分类标识符)是一种用于生成全局唯一且可以lexicographically(字典顺序)排序的标识符。它设计的目标是能够同时满足以下几个特点:全局唯一性:ULID生成的标识符具有足够的唯一性,能够在分布式系统中广泛应用......
  • WPF笔记6——静态资源(StaticResource) 与 动态资源(DynamicResource)
    示例代码1前台代码:点击查看代码<Windowx:Class="TestWPF.Window1"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:d="http://sc......
  • WPF篇:触发器(Triggers)
    文章目录前言一、触发器简介二、开始1.属性触发器(Trigger)2.事件触发器(EventTrigger)3.数据触发器(DataTrigger)前言今天来记录一下WPF中的触发器(Triggers),触发器是WPF动态界面设计的灵魂所在,触发器是WPF中实现动态UI和交互的强大工具一、触发器简介触发器,顾名思义,就......
  • 【WPF】Prism P1
    视频参考:https://www.bilibili.com/video/BV1nY411a7T8 一、元素布局<Windowx:Class="WPF_Practical.MainWindow"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winf......
  • WPF笔记5——动态资源(DynamicResource)
    动态资源(DynamicResource)是WPF中的一种引用资源的方式,即在运行是查找资源。与StaticResource性比,DynamicResource的性能稍差,因为每次要资源时,都要进行查找。如果资源是在引用它的元素之后定义的,或者资源的值在应用程序运行期间发生变化,那么使用DynamicResource引用的员会自动更......