如何更有效的处理系统异常
来源:互联网 发布:linux的copy命令 编辑:程序博客网 时间:2024/06/09 14:47
一、 问题
对于系统异常,不管是开发(维护)人员还是用户,大家的直观感觉是:系统存在问题。但是对于开发人员,系统异常对话框往往能给出我们异常的类型以及异常发生的地方,所以我们看到异常后,就方便进一步去查找错误,并进行修正。但是,当用户遇到一个系统异常时,心中就充满了厌恶,他从异常中并不能找到处理异常的方法,唯一的方法是把异常发给开发人员进行分析(如果这也算好处的话)。但若在客户现场发生了系统异常,我们应该通过日志来记录,并通过对话框提示用户如何应对(或重启系统、或联系维护人员)。所以,我们应该尽量避免系统在客户现场弹出系统异常。
二、 解决方案
不管什么系统,完全没有bug,没有漏洞是不可能的,关键是应对这些问题的策略。现在微软的系统,若是发生了系统异常,它会弹出一个对话框,提示用户是否把异常发给微软处理,当然其中也有重启系统、恢复数据的提示操作。那么我们的系统呢?对于能够预测得到的异常,能够捕捉的异常,当然,我们也要给用户提示解决方案(或重启,或验证数据合法性及操作流程正确性),对于一些我们不能预测的异常,也要给出相应解决方案,例如:若网络问题、配置问题,或服务器重启等,应提醒用户检查或联系管理员处理,若是无法确认的问题,可以联系系统维护人员处理等。这样,用户在使用我们的系统时,才有更强的安全感。
三、 具体方法
那么如何才能避免弹出系统异常并给出处理方法呢?首先,要尽量捕获系统所有异常,然后对系统进行分类处理。
1) 捕获异常:
对于可以预测的异常,我们在系统的相应位置都会进行捕获并处理,例如:在业务逻辑层进行业务逻辑检查时,发现逻辑不正确,然后就会抛出CheckException异常,然后在客户端的相应位置进行捕获,并弹出对话框,提示用户出现了什么问题,应如何正确解决等;对于权限处理的,我们也会弹出SecurityException异常;对于网络问题,我们会弹出RemotingException异常,对于服务器不可用的问题,我们会弹出ServerExceiption异常或SocketException异常。但是还有些异常是我们无法预知的,这时应如何处理呢?难道处处捕获Exception吗?这是不够现实的,可喜的是,.net Framework中已经给我们提供了相应的处理方法。
对于异常的处理,你已经会想到:对于UI所在的主线程中的异常,我们可以捕获异常,并弹出提示,但若是其它线程中的异常应该如何处理呢?这些问题,.net Framework设计人员也想到了,针对这两种异常的处理办法分别是:通过Application.ThreadException事件捕获UI主线程异常,并进行相应处理;通过AppDomain.CurrentDomain.UnhandledException事件捕获其它异常,但是此事件只能探测到非UI线程异常,却不能阻止系统异常的弹出,所以可以在此处以日志的形式记录系统异常。
/// <summary>
/// 程序入口类
/// </summary>
static class Program
{
[STAThread]
[SecurityPermission(SecurityAction.Demand, Flags = SecurityPermissionFlag.ControlAppDomain)]
public static void Main(string[] args)
{
// 添加一个线程事件处理器来处理UI线程相关异常
Application.ThreadException += new ThreadExceptionEventHandler(Form1_UIThreadException);
// 始终将异常传送到ThreadException 处理程序。忽略应用程序配置文件。
Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);
// 添加一个事件处理器来处理非UI线程异常.
AppDomain.CurrentDomain.UnhandledException +=
new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);
// 运行程序.
Application.Run(new Form1());
}
// 通过弹出对话框处理UI线程异常,并询问用户是否终止程序继续运行.
private static void Form1_UIThreadException(object sender, ThreadExceptionEventArgs t)
{
DialogResult result = DialogResult.Cancel;
try
{
result = ShowThreadExceptionDialog("Windows Forms Error", t.Exception);
}
catch
{
try
{
MessageBox.Show("Fatal Windows Forms Error",
"Fatal Windows Forms Error", MessageBoxButtons.AbortRetryIgnore, MessageBoxIcon.Stop);
}
finally
{
Application.Exit();
}
}
// Exits the program when the user clicks Abort.
if (result == DialogResult.Abort)
Application.Exit();
}
// 通过弹出对话框处理非UI线程异常,并询问用户是否终止程序继续运行.
// 注意:这类异常不能终止异常,所以它仅能以日志的形式记录下来,并通知用户。
private static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)
{
try
{
Exception ex = (Exception)e.ExceptionObject;
string errorMsg = "An application error occurred. Please contact the adminstrator " +
"with the following information:/n/n";
// Since we can't prevent the app from terminating, log this to the event log.
if (!EventLog.SourceExists("ThreadException"))
{
EventLog.CreateEventSource("ThreadException", "Application");
}
// Create an EventLog instance and assign its source.
EventLog myLog = new EventLog();
myLog.Source = "ThreadException";
myLog.WriteEntry(errorMsg + ex.Message + "/n/nStack Trace:/n" + ex.StackTrace);
}
catch (Exception exc)
{
try
{
MessageBox.Show("Fatal Non-UI Error",
"Fatal Non-UI Error. Could not write the error to the event log. Reason: "
+ exc.Message, MessageBoxButtons.OK, MessageBoxIcon.Stop);
}
finally
{
Application.Exit();
}
}
}
// 创建异常处理信息,并以对话框的形式通知用户。
private static DialogResult ShowThreadExceptionDialog(string title, Exception e)
{
string errorMsg = "An application error occurred. Please contact the adminstrator " +
"with the following information:/n/n";
errorMsg = errorMsg + e.Message + "/n/nStack Trace:/n" + e.StackTrace;
return MessageBox.Show(errorMsg, title, MessageBoxButtons.AbortRetryIgnore,
MessageBoxIcon.Stop);
}
}
/// <summary>
/// 主窗口类
/// </summary>
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
// 当点击时,弹出UI线程异常
private void kdButton1_Click(object sender, EventArgs e)
{
throw new ArgumentException("The parameter was invalid");
}
// 新建一个线程,使之独立于Windows窗口,并抛出异常.
private void kdButton2_Click(object sender, EventArgs e)
{
ThreadStart newThreadStart = new ThreadStart(newThread_Execute);
Thread newThread = new Thread(newThreadStart);
newThread.Start();
}
// 对立线程抛出的非UI异常.
void newThread_Execute()
{
throw new Exception("The method or operation is not implemented.");
}
}
2) 异常分类处理
对于异常的分类处理,就需要我们对异常进行分类了。这需要我们针对不同的异常定义不通的异常类型,并在适当的地方抛出,当然这些异常都是可预知的,我们在代码中可以捕获并处理。但是,对于一些我们不可预知的类应该如何处理呢?这个不用担心,.net Framework已经定义了许多异常类型,足够我们使用的,只要我们正确分别处理就好了,比如:有些类型的异常是系统配置错误,我们可以提示解决办法,或直接让用户联系管理员,对于一些系统漏洞(真正的不可预知),可以提示用户联系维护人员,或像微软那样让用户直接把异常信息发给维护部门。
四、 总结
为了解决系统异常,我们花费了许多时间,但系统异常是不可避免的。所以我们不可能解决所有系统异常,但是我们可以使系统异常以更加友好的方式弹出,我们可以对不同类型的系统异常,给出用户建议性的解决办法。用户在遇到系统异常时,不再会有烦躁不安的心情,不再有抱怨的态度,不再有无所适从的举措,有的只是安全,放心,稳妥的感觉,并及时地以正确的方式进行处理。
- 如何更有效的处理系统异常
- 如何更有效的找工作
- 如何更有效的学习
- 如何更有效的读书
- 针对有效的错误处理设计异常管理系统
- [转]如何更有效的利用MSDN
- [转]如何更有效的利用MSDN
- 如何让你的网络广告更有效
- 如何更有效的进行面试
- 如何更有效的进行面试
- 如何更有效的发布招聘信息
- 如何更有效的进行面试
- 如何更有效的编写程序
- 如何更有效的进行面试
- Java异常处理--更优雅的处理
- 更有效的英語學習
- 更有效的C + +
- 如何学习英语更有效
- Windows 7 Beta 下载
- C# 处理Excel 转
- 千一网络发布 HighlightKey v1.0
- LINQ To XML And RSS
- 这几天
- 如何更有效的处理系统异常
- 共建网,宠物
- 为什么没什么人玩呢?凰华学院主校剧情有感
- 限制进程使用的资源
- Linux系统调用列表
- HashSet为什么可以插入重复的项?
- SVN的Local方式:个人源码管理的好办法
- jdk环境变量自动设置工具
- 【星海数据】电信、网通、铁通空间,1G空间只需月付30元