首页 > 其他分享 >WPF的APP生命周期以及全局异常捕获

WPF的APP生命周期以及全局异常捕获

时间:2023-01-26 19:55:43浏览次数:47  
标签:生命周期 APP 捕获 应用程序 线程 窗体 WPF 异常 App

WPF的APP生命周期以及全局异常捕获

APP生命周期

wpf项目目录中有一个App.xaml.cs文件,该文件中App是一个partical类,与之对应的另一partical部分在App.g.i.cs文件中,该文件是在编译的时候WPF自动生成的。程序的入口Main方法在该文件中定义。

[System.STAThreadAttribute()]
[System.Diagnostics.DebuggerNonUserCodeAttribute()]
[System.CodeDom.Compiler.GeneratedCodeAttribute("PresentationBuildTasks", "7.0.1.0")]
public static void Main() {
    WpfApp.App app = new WpfApp.App();
    app.InitializeComponent();//初始化Xaml
    app.Run();//程序运行
}

APP类继承自Application,常见的生命周期事件有以下几个:

  • Startup:在调用 Application 对象的 Run 方法时发生
  • Navigating:在应用程序中的导航器请求新导航时发生(针对Browser类型的应用)
  • LoadCompleted:在已经加载、分析并开始呈现应用程序中的导航器导航到的内容时发生
  • Navigated:在已经找到应用程序中的导航器要导航到的内容时发生,尽管此时该内容可能尚未完成加载
  • NavigationFailed:在应用程序中的导航器在导航到所请求内容时出现错误的情况下发生
  • NavigationProgress:在由应用程序中的导航器管理的下载过程中定期发生,以提供导航进度信息
  • NavigationStopped:在调用应用程序中的导航器的 StopLoading 方法时发生,或者当导航器在当前导航正在进行期间请求了一个新导航时发生
  • SessionEnding:在用户通过注销或关闭操作系统而结束 Windows 会话时发生
  • Activated:当应用程序成为前台应用程序时发生,App任意一个窗口激活
  • Deactivated:当应用程序停止作为前台应用程序时发生,App中所有窗口非激活
  • Exit:在应用程序关闭之前发生(无法像SessionEnding事件进行取消)

对于普通窗体程序,从开始到结束会依次调用如下事件

-----App_Startup
-----App_Navigating
-----App_Activated
-----App_Exit

窗体生命周期事件

在APP运行后,会启动窗体,窗体常用的声明周期事件如下:

  • SourceInitialized:操作系统给窗口分配句柄的时候触发,注意WPF窗体里面的控件是没有句柄的
  • ContentRendered:窗体内容渲染后触发
  • Loaded:窗体布局加载完成即准备好交互后触发
  • Activated:窗体激活
  • Deactivated:窗体失去焦点
  • Closing:调用关闭窗体时触发,此时可以取消操作
  • Closed:窗体关闭后

全局异常捕获

对于异常捕获一般使用try-catch语句进行捕获,但是对于全局的异常可以在App中进行捕获。

  • DispatcherUnhandledException:在异常由应用程序引发但未进行处理时发生针对UI线程,无法捕获多线程异常
  • AppDomain.CurrentDomain.UnhandledException:专门捕获所有线程中的异常
  • TaskScheduler.UnobservedTaskException:专门捕获Task异常

案例:

APP中进行全局异常捕获

public partial class App : Application
{
    public App()
    {
        //在异常由应用程序引发但未进行处理时发生。UI线程
        //无法捕获多线程异常
        this.DispatcherUnhandledException += App_DispatcherUnhandledException;
        //专门捕获所有线程中的异常
        AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
        //专门捕获Task异常
        TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
    }
    private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
    {
        Debug.WriteLine("-----App_DispatcherUnhandledException--UI线程" + e.Exception.Message);
    }
    private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
    {
        Debug.WriteLine("-----CurrentDomain_UnhandledException--其他线程" + (e.ExceptionObject as Exception).Message);
    }
    private void TaskScheduler_UnobservedTaskException(object? sender, UnobservedTaskExceptionEventArgs e)
    {
        Debug.WriteLine("-----TaskScheduler_UnobservedTaskException--Task测试" + e.Exception.Message);
        e.SetObserved();
    }
}

窗体中抛异常

public partial class MainWindow : Window
{
    int i = 0;
    public MainWindow()
    {
        InitializeComponent();
        //1、ui线程异常测试
        _ = 1 / i;

        //2、其他线程异常测试
        new Thread(new ThreadStart(() => { _ = 1 / i; })).Start();

        //3、Task异常测试
        Task.Run(() =>
        {
            _ = 1 / i;
        });
    }   
}
异常 结果 说明
只打开异常1 -----App_DispatcherUnhandledException--UI线程-----CurrentDomain_UnhandledException--其他线程 UI线程中的异常DispatcherUnhandledException和AppDomain.CurrentDomain.UnhandledException均能捕获到
只打开异常2 -----CurrentDomain_UnhandledException--其他线程 只有AppDomain.CurrentDomain.UnhandledException可以捕获
只打开异常3 -----TaskScheduler_UnobservedTaskException--Task测试 只有TaskScheduler.UnobservedTaskException可以捕获到Task异常

备注:Task中的异常并不是立刻就能捕获到的,而是等到垃圾回收的时候进行捕获。如果想立刻进行捕获则可以调用GC.Collect(0);GC.WaitForPendingFinalizers();

标签:生命周期,APP,捕获,应用程序,线程,窗体,WPF,异常,App
From: https://www.cnblogs.com/qsnn/p/17068129.html

相关文章

  • WPF的APP生命周期以及全局异常捕获
    WPF的APP生命周期以及全局异常捕获APP生命周期wpf项目目录中有一个App.xaml.cs文件,该文件中App是一个partical类,与之对应的另一partical部分在App.g.i.cs文件中,该文件是在......
  • Spring Bean生命周期——从源码角度详解Spring Bean的生命周期(上)
    文章目录​​写在前面​​​​一、SpringBean元信息配置阶段​​​​1、使用xml方式配置BeanDefinition​​​​代码实例​​​​2、使用Properties资源配置BeanDefiniti......
  • WPF-3D图形
    WPF-3D图形WPF的3D功能可以在不编写任何c#代码的情况下进行绘制,只需要使用xaml即可完成3D图形的渲染。本文主要讲述了WPF-3D中的关键概念,以及常用到的命中测试、2d控件如......
  • 问题:RuntimeError: Model class LuffyAPI.apps.user.models.UserInfo doesn't declare
    问题截图  报错原因提示app未注册,但实际上已经注册的#1.#settings配置文件移动后要将这个settings添加到环境变量中sys.path.insert(0,BASE_DIR)#将所有app......
  • call apply bind的作用和区别?
    bind改变this指向不直接调用、call和apply改变this指向直接调用、apply接收第二个参数为数组、call用于对象的继承、伪数组转换成真数组、apply用于找出数组中的最大值和......
  • mybatis添加mapper映射文件的四种方式
    一、绝对路径引入(不推荐使用)<!--1.绝对路径引入--><mapperurl="file:\\\D:\stsbundle\workplace\mybatis_demo\src\main\resources\mapper\UserMapper.xml"/>二......
  • 关于 animate 和 ApplyMethod 的区别
    前者尽量不要使用,因为多个animate出现后只会执行最后一个后者目前没有什么bug,但是如果使用AnimationGroup可能会出现bug:defashg(*args,**kwarg......
  • JavaScript学习笔记—函数中的call和apply
    调用函数除了通过函数()这种形式外,还可以通过其他的方式来调用函数,比如可以通过调用函数的call()和apply()两个方法来调用函数函数.call()函数.apply()call和apply除......
  • 与终端设备交互Mapper组件
    Mapper架构从与KubeEdge边部分EdgeCore对接的协议划分,终端设备可以分为通过MQTT协议进行对接的终端设备和通过HTTP进行对接的终端设备。1)通过MQTT协议进行对接的终端设......
  • Oracle宣布Java7生命周期终结
     Oracle于2015年4月停止在公共渠道发布Java7安全补丁和升级包,以敦促用户迁移至Java8或购买Java7的长期商业支持服务。后续可能有其它第三方机构为其提供公......