WPF异常捕获,并使程序不崩溃!

简介: 原文:WPF异常捕获,并使程序不崩溃! 在.NET中,我们使用try-catch-finally来处理异常。但,当一个Exception抛出,抛出Exception的代码又没有被try包围时,程序就崩溃了。
原文: WPF异常捕获,并使程序不崩溃!

在.NET中,我们使用try-catch-finally来处理异常。但,当一个Exception抛出,抛出Exception的代码又没有被try包围时,程序就崩溃了。

这些异常往往是你没有注意到的。在WPF中,提供了一种处理这些个异常的方式。

举例来说明。

1.先抛出个异常,不用try包围它。

在MainWindow上添加一个如下的Button。


<Window x:Class="HandlingAnUnhandledException.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <StackPanel>
        <Button Click="OnClick">
            <Button.Template>
                <ControlTemplate>
                    <Grid>
                        <Ellipse Height="100" Width="250" Fill="Pink"/>
                        <TextBlock Text="Button to Throw Exception by DebugLZQ" VerticalAlignment="Center" HorizontalAlignment="Center"/>
                    </Grid>
                </ControlTemplate>
            </Button.Template>
        </Button>
    </StackPanel>
</Window>

在Button的Click事件中抛出个异常

        private void OnClick(object sender, RoutedEventArgs e)
        {
            throw new InvalidOperationException("Something has gone wrong.");
        }

如果,我们Ctrl+F5运行这个程序,点击按钮,程序就崩溃了。
WPF如何解决这个问题呢?

2.WPF处理这种异常的方法

在App.xaml.cs中订阅DispatcherUnhandledException事件,并添加相应的事件处理。

App.xaml.cs如下:


    public partial class App : Application
    {
        public App()
        {
            DispatcherUnhandledException += App_DispatcherUnhandledException;
        }

        void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {            
            MessageBox.Show("Error encountered! Please contact support."+ Environment.NewLine + e.Exception.Message);
            //Shutdown(1);
            e.Handled = true;
        }
    }

这时,当我们Ctrl+F5运行程序。

 这样,异常就被捕获并处理了,程序没有崩溃。  


  所有 WPF 应用程序启动时都会加载两个重要的线程:一个用于呈现用户界面,另一个用于管理用户界面。呈现线程是一个在后台运行的隐藏线程,因此我们通常面对的唯一线程就是 UI 线程。

  这种方法只能捕捉UI线程的异常,及使用了Dispatcher进行线程关联了的线程(其实Dispatcher.Invoke/BeginInvoke就是将要执行的代码,扔到UI线程去执行)的异常。不能捕捉普通的子线程异常。

如: 

private void OnClick(object sender, RoutedEventArgs e)
{
   Dispatcher.BeginInvoke(new Action(() => { throw new InvalidOperationException("Something has gone wrong."); }));
}

也可以正常捕获。

而:


private void OnClick(object sender, RoutedEventArgs e)
{
   Thread t = new Thread(() => { throw new InvalidOperationException("Something has gone wrong."); });
   t.IsBackground = true;
   t.Start();
}

则不能捕获。 

感谢veboys博友的指点~

------------------------------------------

同样的,即使我们用一个try-catch包围如下的异常,异常也不会被Handle:


try
{
    var thread = new Thread(() => {throw new Exception(); });
    thread.Start();
}
catch (Exception)
{
    MessageBox.Show("Will not execute!");
    throw;
}

 


try
{
    Task.Run(() =>{throw new Exception(); });
}
catch (Exception)
{
    MessageBox.Show("Will not execute!");
}

 

--------------

对应Async await 异常:


private async void ButtonBase_OnClick(object sender, RoutedEventArgs e)
        {
            try
            {
                await Task.Run(() => { throw new Exception(); });
            }
            catch (Exception)
            {
                MessageBox.Show("Will execute!");
            }
        }

处理Unhandled exception异常 如下:TaskScheduler.UnobservedTaskException


    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            RegisterEvents();
            base.OnStartup(e);
        }

        private void RegisterEvents()
        {
            TaskScheduler.UnobservedTaskException += (sender, args) =>
            {
                MessageBox.Show(args.Exception.Message);
                args.SetObserved();
            };

            AppDomain.CurrentDomain.UnhandledException += (sender, args) => MessageBox.Show("Unhandled exception.");
        }
    }

 

目录
相关文章
|
C# Windows
WPF 获取程序路径的一些方法,根据程序路径获取程序集信息
原文:WPF 获取程序路径的一些方法,根据程序路径获取程序集信息 一、WPF 获取程序路径的一些方法方式一 应用程序域 //获取基目录即当前工作目录 string str_1 = System.
1717 0
|
3月前
|
C#
WPF/C#:程序关闭的三种模式
WPF/C#:程序关闭的三种模式
62 0
|
5月前
|
C#
WPF/C#:程序关闭的三种模式
WPF/C#:程序关闭的三种模式
78 3
|
C#
WPF防止程序多次运行
WPF防止程序多次运行
220 0
WPF界面无法正常显示(资源引用,如转换器),但程序正常运行
WPF界面无法正常显示(资源引用,如转换器),但程序正常运行
WPF界面无法正常显示(资源引用,如转换器),但程序正常运行
WPF从外部文件或者程序集加载样式或其他静态资源
WPF从外部文件或者程序集加载样式或其他静态资源
WPF从外部文件或者程序集加载样式或其他静态资源
|
Java 测试技术 C#
WPF的APP生命周期以及全局异常捕获
WPF的APP生命周期以及全局异常捕获,详细介绍了整个APP的生命周期和窗体生命周期,以及如何使用全局异常捕获
|
Java C# 程序员
WPF程序中的弱事件模式
原文:WPF程序中的弱事件模式 在C#中,得益于强大的GC机制,使得我们开发程序变得非常简单,很多时候我们只需要管使用,而并不需要关心什么时候释放资源。但是,GC有的时并不是按照我们所期望的方式工作。 例如,我想实现一个在窗口的标题栏中实时显示当前的时间,一个比较常规的做法如下:     var...
1144 0
|
C#
WPF全局异常捕获
跟着《WPF专业编程开发指南》这书打的代码的,自己在正式项目中测试通过,可以抓取到全局的异常,用的log4net来记录日志 核心代码: 写在App.xaml.cs中 /// <summary> /// App.
5420 0
|
C#
WPF如何为程序添加splashScreen(初始屏幕)
原文:WPF如何为程序添加splashScreen(初始屏幕) 一、考虑到大部分的splashscreen其实都只是一个图片,所以最简单的做法是,先导入一张图片,然后设置它的生成操作为“splash screen”   二、通过程序设置SplashScreen public parti...
1416 0