詳解WPF中的APP生命周期以及全局異常捕獲
APP生命周期
wpf項(xiàng)目目錄中有一個(gè)App.xaml.cs文件,該文件中App是一個(gè)partical類,與之對(duì)應(yīng)的另一partical部分在App.g.i.cs文件中,該文件是在編譯的時(shí)候WPF自動(dòng)生成的。程序的入口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();//程序運(yùn)行 }
APP類繼承自Application,常見的生命周期事件有以下幾個(gè):
Startup
:在調(diào)用 Application 對(duì)象的 Run 方法時(shí)發(fā)生Navigating
:在應(yīng)用程序中的導(dǎo)航器請(qǐng)求新導(dǎo)航時(shí)發(fā)生(針對(duì)Browser類型的應(yīng)用)LoadCompleted
:在已經(jīng)加載、分析并開始呈現(xiàn)應(yīng)用程序中的導(dǎo)航器導(dǎo)航到的內(nèi)容時(shí)發(fā)生Navigated
:在已經(jīng)找到應(yīng)用程序中的導(dǎo)航器要導(dǎo)航到的內(nèi)容時(shí)發(fā)生,盡管此時(shí)該內(nèi)容可能尚未完成加載NavigationFailed
:在應(yīng)用程序中的導(dǎo)航器在導(dǎo)航到所請(qǐng)求內(nèi)容時(shí)出現(xiàn)錯(cuò)誤的情況下發(fā)生NavigationProgress
:在由應(yīng)用程序中的導(dǎo)航器管理的下載過程中定期發(fā)生,以提供導(dǎo)航進(jìn)度信息NavigationStopped
:在調(diào)用應(yīng)用程序中的導(dǎo)航器的 StopLoading 方法時(shí)發(fā)生,或者當(dāng)導(dǎo)航器在當(dāng)前導(dǎo)航正在進(jìn)行期間請(qǐng)求了一個(gè)新導(dǎo)航時(shí)發(fā)生SessionEnding
:在用戶通過注銷或關(guān)閉操作系統(tǒng)而結(jié)束 Windows 會(huì)話時(shí)發(fā)生Activated
:當(dāng)應(yīng)用程序成為前臺(tái)應(yīng)用程序時(shí)發(fā)生,App任意一個(gè)窗口激活Deactivated
:當(dāng)應(yīng)用程序停止作為前臺(tái)應(yīng)用程序時(shí)發(fā)生,App中所有窗口非激活Exit
:在應(yīng)用程序關(guān)閉之前發(fā)生(無法像SessionEnding事件進(jìn)行取消)
對(duì)于普通窗體程序,從開始到結(jié)束會(huì)依次調(diào)用如下事件
-----App_Startup
-----App_Navigating
-----App_Activated
-----App_Exit
窗體生命周期事件
在APP運(yùn)行后,會(huì)啟動(dòng)窗體,窗體常用的聲明周期事件如下:
SourceInitialized
:操作系統(tǒng)給窗口分配句柄的時(shí)候觸發(fā),注意WPF窗體里面的控件是沒有句柄的ContentRendered
:窗體內(nèi)容渲染后觸發(fā)Loaded
:窗體布局加載完成即準(zhǔn)備好交互后觸發(fā)Activated
:窗體激活Deactivated
:窗體失去焦點(diǎn)Closing
:調(diào)用關(guān)閉窗體時(shí)觸發(fā),此時(shí)可以取消操作Closed
:窗體關(guān)閉后
全局異常捕獲
對(duì)于異常捕獲一般使用try-catch語句進(jìn)行捕獲,但是對(duì)于全局的異常可以在App中進(jìn)行捕獲。
DispatcherUnhandledException
:在異常由應(yīng)用程序引發(fā)但未進(jìn)行處理時(shí)發(fā)生針對(duì)UI線程,無法捕獲多線程異常AppDomain.CurrentDomain.UnhandledException
:專門捕獲所有線程中的異常TaskScheduler.UnobservedTaskException
:專門捕獲Task異常
案例:
APP中進(jìn)行全局異常捕獲
public partial class App : Application { public App() { //在異常由應(yīng)用程序引發(fā)但未進(jìn)行處理時(shí)發(fā)生。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; }); } }
異常 | 結(jié)果 | 說明 |
---|---|---|
只打開異常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中的異常并不是立刻就能捕獲到的,而是等到垃圾回收的時(shí)候進(jìn)行捕獲。如果想立刻進(jìn)行捕獲則可以調(diào)用GC.Collect(0);
和GC.WaitForPendingFinalizers();
到此這篇關(guān)于詳解WPF中的APP生命周期以及全局異常捕獲的文章就介紹到這了,更多相關(guān)WPF生命周期 全局異常捕獲內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
C#實(shí)現(xiàn)不同窗體之間傳遞參數(shù)
這篇文章主要介紹了C#實(shí)現(xiàn)不同窗體之間傳遞參數(shù)問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-02-02同步調(diào)用和異步調(diào)用WebService
本文給大家介紹webservice同步調(diào)用和異步調(diào)用,同步調(diào)用就是一個(gè)同步操作會(huì)阻塞整個(gè)當(dāng)前的進(jìn)程,直到這個(gè)操作完成才能執(zhí)行下一段代碼,異步調(diào)用不會(huì)阻塞啟動(dòng)操作的調(diào)用線程,調(diào)用程序必須通過輪流檢測,或者等待完成信號(hào)來發(fā)現(xiàn)調(diào)用的完成。小伙伴們跟著小編一起學(xué)習(xí)2015-09-09C#中數(shù)組、ArrayList和List三者的區(qū)別詳解及實(shí)例
這篇文章主要介紹了C#中數(shù)組、ArrayList和List三者的區(qū)別詳解及實(shí)例的相關(guān)資料,需要的朋友可以參考下2016-12-12基于C#實(shí)現(xiàn)Windows服務(wù)狀態(tài)啟動(dòng)和停止服務(wù)的方法
這篇文章主要介紹了基于C#實(shí)現(xiàn)Windows服務(wù)狀態(tài)啟動(dòng)和停止服務(wù)的方法,詳細(xì)講述了實(shí)現(xiàn)這一功能的具體步驟,代碼簡潔易懂,需要的朋友可以參考下2014-09-09