如果您熟悉 C# 或可能與 WPF 一起使用的任何其他 .NET 語言,那麼異常處理對您來說應該不陌生:隻要您有一段可能會引發異常的代碼,那麼您應該将其包裝在 try-catch 塊中以優雅地處理異常。
由于這樣一個簡單且容易避免的錯誤,使用者将被迫關閉您的應用程式。是以,如果您知道事情可能會出錯,那麼您應該使用 try-catch 塊,如下所示:
private void Button_Click(object sender, RoutedEventArgs e)
{
string s = null;
try
{
s.Trim();
}
catch(Exception ex)
{
MessageBox.Show("A handled exception just occurred: " + ex.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
}
}
但是,有時即使是最簡單的代碼也會引發異常,而不是用 try-catch 塊包裝每一行代碼,WPF 允許您全局處理所有未處理的異常。這是通過Application 類上的DispatcherUnhandledException事件完成的。如果訂閱,WPF 将在抛出異常時調用訂閱方法,而該異常未在您自己的代碼中處理。這是一個完整的示例,基于我們剛剛經曆的内容:
<Window x:Class="WpfTutorialSamples.WPF_Application.ExceptionHandlingSample"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ExceptionHandlingSample" Height="200" Width="200">
<Grid>
<Button HorizontalAlignment="Center" VerticalAlignment="Center" Click="Button_Click">
Do something bad!
</Button>
</Grid>
</Window>
using System;
using System.Windows;
namespace WpfTutorialSamples.WPF_Application
{
public partial class ExceptionHandlingSample : Window
{
public ExceptionHandlingSample()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
string s = null;
try
{
s.Trim();
}
catch(Exception ex)
{
MessageBox.Show("A handled exception just occurred: " + ex.Message, "Exception Sample", MessageBoxButton.OK, MessageBoxImage.Warning);
}
s.Trim();
}
}
}
請注意,在 try-catch 塊之外額外調用了 Trim() 方法,處理第一個調用,而第二個則沒有。對于第二個,我們需要 App.xaml加入全局異常處理方法:
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
//UI線程未捕獲異常處理事件
this.DispatcherUnhandledException += App_DispatcherUnhandledException;
//Task線程内未捕獲異常處理事件
TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
//非UI線程未捕獲異常處理事件
AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;
}
private void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
MessageBox.Show("系統異常1".Replace("{Exception}", $"{e.ExceptionObject}"));//如果出現線上程裡,會一直彈出
}
catch
{
}
}
private void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
{
try
{
e.SetObserved();
MessageBox.Show("系統異常2" + e.Exception);
}
catch
{
}
}
private void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
{
try
{
e.Handled = true;
MessageBox.Show("系統異常3" + e.Exception);
}
catch
{
}
}
}