詳解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();
到此這篇關於詳解WPF中的APP生命周期以及全局異常捕獲的文章就介紹到這瞭,更多相關WPF生命周期 全局異常捕獲內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!