首頁 > 軟體

詳解WPF中的APP生命週期以及全域性異常捕獲

2023-03-02 18:00:14

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生命週期 全域性異常捕獲內容請搜尋it145.com以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援it145.com!


IT145.com E-mail:sddin#qq.com