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程序的异常捕获总结

  • 相关阅读:
    398. Random Pick Index
    382. Linked List Random Node
    645. Set Mismatch
    174. Dungeon Game
    264. Ugly Number II
    115. Distinct Subsequences
    372. Super Pow
    LeetCode 242 有效的字母异位词
    LeetCode 78 子集
    LeetCode 404 左叶子之和
  • 原文地址:https://www.cnblogs.com/DebugLZQ/p/3161185.html
Copyright © 2011-2022 走看看