C# WPF上位机开发(闪退问题的处理)

2023-12-22 11:34:29

【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】

? ? ? ? 有一些上位机程序本身是需要长时间运行的,比如一些监控程序,或者是需要24h作业的业务系统等等。在这过程中,如果上位机软件发生了闪退的问题,那么其实是比较麻烦的。因为这个时候,我们能够拿到的信息,基本上只剩下程序的运行日志。但是,log有一个不好的地方,那就是记录的log和真正出问题的地方,很可能还有蛮长的一段距离,不一定能够帮助我们找到问题的root cause。所以这个时候,最好c# .net,或者wpf能够帮助我们提供闪退的处理机制,这是比较好的处理方法。

? ? ? ? 所以为了解决这个问题,通过检索,正好发现了c# .net的确提供了类似的处理机制,我们要做的,只是把相关的函调函数加上就可以了。

1、相关的函数需要提前注册到App.xaml.cs

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

        /* other code  */

    }

2、异常处理回调函数添加

? ? ? ? 异常的处理部分目前只需要在RegisterEvents中添加即可。当前,支持的异常主要有三种情形,一种是task exception,一种是非ui exception,还有一种是ui exception。三种exception如果需要处理的话,添加对应的回调函数即可,

        private void RegisterEvents()
        {
            //task exception
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            
            //not ui exception
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            //ui exception
            this.DispatcherUnhandledException += App_DispatcherUnhandledException;

        }

3、具体exception的处理

? ? ? ? 具体exception怎么处理,完全取决于用户自己的用途。比如说,有的exception如果不想处理,直接忽略掉,这是可以的;还有的异常,是因为当时代码有bug,造成了闪退,那么这个时候最好把相关的异常信息保存到log里面,等待回头继续处理。总之,异常的处理是一个见仁见智、灵活处理的过程。大部分情况下,我们可以和本篇文章的主题一样,把它看成一个闪退的预防手段,也是可以的。

        // task exception
        private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            try
            {
                var exception = e.Exception as Exception;
                if (exception != null)
                {
                    HandleException(exception);
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            finally
            {
                e.SetObserved();
            }
        }

        // not ui exception  
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                var exception = e.ExceptionObject as Exception;
                if (exception != null)
                {
                    HandleException(exception);
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            finally
            {
                //give up
            }
        }

        // ui exception
        private static void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                HandleException(e.Exception);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            finally
            {
                e.Handled = true;
            }
        }
        private static void HandleException(Exception ex)
        {
            Console.WriteLine(ex.Message + "\r\n" + ex.StackTrace);
        }

4、测试方法

? ? ? ? 异常处理的大部分代码都是在App.xaml.cs完成的,所以如果需要测试的话,首先需要注册一个界面,然后创建一个按钮,在按钮的响应函数中故意添加一个异常抛出的代码,比如像下面这样,

        // button invoke function
        private void StartButton_Click(object sender, RoutedEventArgs e)
        {
            throw new Exception();
        }

? ? ? ? 有了这个代码之后,我们就可以调试软件,在App_DispatcherUnhandledException中创建断点,看注册的异常处理函数是不是真的会被调用到,如果可以,那没问题;如果还是不行,那就去看看代码的原因了。

5、附录

? ? ? ? 最后给出完整的测试代码,希望对大家开发软件、调试闪退问题有所帮助。

using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Threading.Tasks;
using System.Windows;

namespace WpfApp
{
    /// <summary>
    /// App.xaml 的交互逻辑
    /// </summary>
    public partial class App : Application
    {
        protected override void OnStartup(StartupEventArgs e)
        {
            RegisterEvents();
            base.OnStartup(e);
        }

        private void RegisterEvents()
        {
            //task exception
            TaskScheduler.UnobservedTaskException += TaskScheduler_UnobservedTaskException;
            
            //not ui exception
            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException;

            //ui exception
            this.DispatcherUnhandledException += App_DispatcherUnhandledException;

        }

        // task exception
        private static void TaskScheduler_UnobservedTaskException(object sender, UnobservedTaskExceptionEventArgs e)
        {
            try
            {
                var exception = e.Exception as Exception;
                if (exception != null)
                {
                    HandleException(exception);
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            finally
            {
                e.SetObserved();
            }
        }

        // not ui exception  
        private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
        {
            try
            {
                var exception = e.ExceptionObject as Exception;
                if (exception != null)
                {
                    HandleException(exception);
                }
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            finally
            {
                //give up
            }
        }

        // ui exception
        private static void App_DispatcherUnhandledException(object sender, System.Windows.Threading.DispatcherUnhandledExceptionEventArgs e)
        {
            try
            {
                HandleException(e.Exception);
            }
            catch (Exception ex)
            {
                HandleException(ex);
            }
            finally
            {
                e.Handled = true;
            }
        }
        private static void HandleException(Exception ex)
        {
            Console.WriteLine(ex.Message + "\r\n" + ex.StackTrace);
        }
    }
}

文章来源:https://blog.csdn.net/feixiaoxing/article/details/135146640
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。