天天看點

WPF 中處理異常方法

如果您熟悉 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
            {
            }
        }
    }