zoukankan      html  css  js  c++  java
  • 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运行程序。

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

     Update:刚百度了一下:WinForm也有类似的机制,请参考Kevin Gao的这篇博文:C# winform 捕获全局异常.

     Update

      所有 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.");
            }
        }

     Update

    WPF程序的异常捕获总结

  • 相关阅读:
    微信小程序-上传多张图片加进度条(支持预览、删除)
    php中120个内置函数
    angular6 NgModule中定义模块module
    Aliasing input/output properties
    angular6 Can't bind to 'zzst' since it isn't a known property of
    [转]DOM 中 Property 和 Attribute 的区别
    Angular6
    [转]VirtualBox 修改UUID实现虚拟硬盘复制
    pthread_create如何传递两个参数以上的参数
    linux 线程操作问题undefined reference to 'pthread_create'的解决办法(cmake)
  • 原文地址:https://www.cnblogs.com/DebugLZQ/p/3161185.html
Copyright © 2011-2022 走看看