这篇文章主要讲解了“WPF中的APP生命周期及全局异常捕获源码分析”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“WPF中的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();
感谢各位的阅读,以上就是“WPF中的APP生命周期及全局异常捕获源码分析”的内容了,经过本文的学习后,相信大家对WPF中的APP生命周期及全局异常捕获源码分析这一问题有了更深刻的体会,具体使用情况还需要大家实践验证。这里是亿速云,小编将为大家推送更多相关知识点的文章,欢迎关注!
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。