【 声明:版权所有,欢迎转载,请勿用于商业用途。 联系信箱:feixiaoxing @163.com】
? ? ? ? 有一些上位机程序本身是需要长时间运行的,比如一些监控程序,或者是需要24h作业的业务系统等等。在这过程中,如果上位机软件发生了闪退的问题,那么其实是比较麻烦的。因为这个时候,我们能够拿到的信息,基本上只剩下程序的运行日志。但是,log有一个不好的地方,那就是记录的log和真正出问题的地方,很可能还有蛮长的一段距离,不一定能够帮助我们找到问题的root cause。所以这个时候,最好c# .net,或者wpf能够帮助我们提供闪退的处理机制,这是比较好的处理方法。
? ? ? ? 所以为了解决这个问题,通过检索,正好发现了c# .net的确提供了类似的处理机制,我们要做的,只是把相关的函调函数加上就可以了。
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
RegisterEvents();
base.OnStartup(e);
}
/* other code */
}
? ? ? ? 异常的处理部分目前只需要在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;
}
? ? ? ? 具体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);
}
? ? ? ? 异常处理的大部分代码都是在App.xaml.cs完成的,所以如果需要测试的话,首先需要注册一个界面,然后创建一个按钮,在按钮的响应函数中故意添加一个异常抛出的代码,比如像下面这样,
// button invoke function
private void StartButton_Click(object sender, RoutedEventArgs e)
{
throw new Exception();
}
? ? ? ? 有了这个代码之后,我们就可以调试软件,在App_DispatcherUnhandledException中创建断点,看注册的异常处理函数是不是真的会被调用到,如果可以,那没问题;如果还是不行,那就去看看代码的原因了。
? ? ? ? 最后给出完整的测试代码,希望对大家开发软件、调试闪退问题有所帮助。
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);
}
}
}