博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
【第一篇笔记】C# 全局容错,全局异常
阅读量:5273 次
发布时间:2019-06-14

本文共 8016 字,大约阅读时间需要 26 分钟。

网上找到两个方式,一个简单的只是做个记录,另一个能像QQ一样提交到后台。

方法一:

static class Program    {        ///         /// 应用程序的主入口点。        ///         [STAThread]        static void Main()        {            try            {                //设置应用程序处理异常方式:ThreadException处理                Application.SetUnhandledExceptionMode(UnhandledExceptionMode.CatchException);                //处理UI线程异常                Application.ThreadException += new System.Threading.ThreadExceptionEventHandler(Application_ThreadException);                //处理非UI线程异常                AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException);                #region 应用程序的主入口点                Application.EnableVisualStyles();                Application.SetCompatibleTextRenderingDefault(false);                Application.Run(new Form1());                #endregion            }            catch (Exception ex)            {                string str = GetExceptionMsg(ex,string.Empty);                MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);            }        }        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)        {            string str = GetExceptionMsg(e.Exception, e.ToString());            MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);            //LogManager.WriteLog(str);        }        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)        {            string str = GetExceptionMsg(e.ExceptionObject as Exception, e.ToString());            MessageBox.Show(str, "系统错误", MessageBoxButtons.OK, MessageBoxIcon.Error);            //LogManager.WriteLog(str);        }        ///         /// 生成自定义异常消息        ///         /// 异常对象        /// 备用异常消息:当ex为null时有效        /// 
异常字符串文本
static string GetExceptionMsg(Exception ex,string backStr) { StringBuilder sb = new StringBuilder(); sb.AppendLine("****************************异常文本****************************"); sb.AppendLine("【出现时间】:" + DateTime.Now.ToString()); if (ex != null) { sb.AppendLine("【异常类型】:" + ex.GetType().Name); sb.AppendLine("【异常信息】:" + ex.Message); sb.AppendLine("【堆栈调用】:" + ex.StackTrace); } else { sb.AppendLine("【未处理异常】:" + backStr); } sb.AppendLine("***************************************************************"); return sb.ToString(); } }
View Code

 

方法二:

转载于:王旭博客 » C# 全局异常处理。

1.本文目标

我们准备做一个程序,具备全局的异常捕获及处理能力,类似大多数知名程序那样弹个窗口,发送错误报告,友好的提示。类似腾讯QQ异常,Firefox异常等异常窗口来进行错误报送,如下图所示:

2.C#异常处理机制简介

C#也跟其他的OOP语言一样能够处理可预见的异常信息,如网络连接失败,文件读取失败,数组越界等异常。当你的程序遇到了异常的时候CLR会抛出一个异常给你,这样你就得到了一个处理异常的机会,这个异常会一层一层的返回给调用者,最后返回到Main方法的起始点中,但是如果你没有进行处理的话最终会被CLR处理,它将终止程序。

 

3. C#全局异常捕获处理

目前为止,很多的程序都是以感觉哪段代码可能异常就把它try起来然后弹个Message的方式进行提示,好一点处理的还会记录日志信息来解决。如果纯粹看简单的错误提示其实是很难找到错误的,尤其是程序越来越大的时候,甚至有时候你都不知道这个错误是哪个模块出现的,是怎么出现的,点击哪个按钮出现的!是不是得去问客户?在我看来极大多数情况是完全没有必要的,我们完全有能力捕获完整的异常。

好了,废话解释完毕,开始构建我们的具备异常处理捕获及处理能力的程序吧!这里以Winform举例,其他的都差不多,如WPF什么的都是可以捕获全局异常的

3.1 构建Bug处理模块

首先我建了个Winform项目命名为 WinformException 用于处理Bug,为了利于以后项目复用 这个项目是单独用于处理Bug的,在该项目中构建了如下窗体。

这个用于对Bug报送的处理,对客户的错误解释界面,你可以根据自己的业务需求进行更改,总而言之把错误完整的保存下来即可。

出现错误不可怕,可怕的是出了错 你却不知道。

窗口的代码如下:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Windows.Forms; namespace WinformException{    public partial class FrmBugReport : Form    {        #region 全局变量        Exception _bugInfo;        #endregion         #region 构造函数        ///         /// Bug发送窗口        ///         /// Bug信息        public FrmBugReport(Exception bugInfo)        {            InitializeComponent();            _bugInfo = bugInfo;            this.txtBugInfo.Text = bugInfo.Message;            lblErrorCode.Text = Guid.NewGuid().ToString();        }         ///         /// Bug发送窗口        ///         /// Bug信息        /// 错误号        public FrmBugReport(Exception bugInfo, string errorCode)        {            InitializeComponent();            _bugInfo = bugInfo;            this.txtBugInfo.Text = bugInfo.Message;            lblErrorCode.Text = errorCode;        }        #endregion         #region 公开静态方法        ///         /// 提示Bug        ///         /// Bug信息        /// 错误号        public static void ShowBug(Exception bugInfo, string errorCode)        {            new FrmBugReport(bugInfo, errorCode).ShowDialog();        }         ///         /// 提示Bug        ///         /// Bug信息        public static void ShowBug(Exception bugInfo)        {            ShowBug(bugInfo, Guid.NewGuid().ToString());        }        #endregion         private void btnDetailsInfo_Click(object sender, EventArgs e)        {            MessageBox.Show("异常详细信息:" + _bugInfo.Message + "\r\n跟踪:" + _bugInfo.StackTrace);        }     }}
View Code

 

这个项目就完成了。

 

3.2 构建异常测试程序

接下来构建我们的测试程序,以及如何捕捉代码。我在解决方案中再建了一个Winform项目命名为WinformTest做测试,如下图所示:

 先来看看我们在 Program.cs 中做了什么手脚吧,这个就是全局捕捉异常的核心代码,Program.cs 代码如下:

using System;using System.Collections.Generic;using System.Windows.Forms; namespace WinformTest{    static class Program    {        ///         /// 应用程序的主入口点。        ///         [STAThread]        static void Main()        {            //全局异常捕捉            Application.ThreadException += Application_ThreadException; //UI线程异常            AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; //多线程异常             Application.EnableVisualStyles();            Application.SetCompatibleTextRenderingDefault(false);            Application.Run(new FrmMain());        }         //UI线程异常        static void Application_ThreadException(object sender, System.Threading.ThreadExceptionEventArgs e)        {            WinformException.FrmBugReport.ShowBug(e.Exception);        }         //多线程异常        static void CurrentDomain_UnhandledException(object sender, UnhandledExceptionEventArgs e)        {            WinformException.FrmBugReport.ShowBug((Exception)e.ExceptionObject);        }    }}

 

第一行我注册了UI线程异常处理事件

  1.  Application.ThreadException += Application_ThreadException; //UI线程异常

这个用于捕获主线程的错误,也就是UI,大多数异常都会聚集在此,我们在该事件中处理了异常,程序则不会强制退出。

 

然后第二行注册了其他多线程异常处理事件(除UI之外的线程)

  1.  AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; //多线程异常

这个用于捕获主线程之外的所有线程的异常,但是无法让程序不被强制退出,当在这里面的代码执行完毕后程序依然会退出!不过幸运的是我们有其他的办法来解决

 

然后看看测试窗体 FrmMain.cs 的代码如下:

using System;using System.Collections.Generic;using System.ComponentModel;using System.Data;using System.Drawing;using System.Text;using System.Threading;using System.Windows.Forms; namespace WinformTest{    public partial class FrmMain : Form    {        public FrmMain()        {            InitializeComponent();        }         //普通异常测试        private void btnTest1_Click(object sender, EventArgs e)        {            throw new Exception("啊..我这行代码异常了...");        }         //多线程异常测试        private void btnTest2_Click(object sender, EventArgs e)        {            Thread th = new Thread(() => { throw new Exception("啊哦,异常错误。"); });            th.IsBackground = true;            th.Start();        }    }}

 

其实就是两个简单的测试而已,点击按钮会弹出如下界面。

我们可以在确定按钮中编写发送到数据库,或者是把bug详细信息存放到txt中。拿到了Exception,由你任意处置吧,我这里把ExceptionStackTrace属性展示到了错误详细信息按钮上,不会看StackTrace的,该反省下了。耐心看下就明白了,是很简单的,它对Bug是如何出现的步骤表示的非常清楚。

好了到此为止,Bug处理也就OK了,还算非常简单的,只是可能我长篇大论了。哈..下次尽量简短..现在应该掌握了对异常的合理处理了吧。

该解决方案的源码下载:

 

小知识:如何处理多线程中的异常,让程序不会强制退出。

你可以这样,把多线程中的任务全部try起来。

Thread t = new Thread((ThreadStart)delegate{try{throw new Exception("多线程异常");}catch (Exception error){MessageBox.Show("线程异常:" + error.Message + Environment.NewLine + error.StackTrace);}});t.Start();
View Code

 

你还可以这样,把异常抛回主线程,这个比较推荐。

Thread t = new Thread((ThreadStart)delegate{try{throw new Exception("非窗体线程异常");}catch (Exception ex){this.BeginInvoke((Action)delegate{throw ex;});}});t.Start();
View Code

 

转载于:https://www.cnblogs.com/mumupudding/p/4599363.html

你可能感兴趣的文章
ajax与java后台交互
查看>>
面向对象之元类
查看>>
MySQL常用函数
查看>>
实现绘制图形的ToolBar
查看>>
C# 串口接收数据中serialPort.close()死锁
查看>>
Python3控制结构与函数
查看>>
字符串方法title()、istitle()
查看>>
yield语句
查看>>
java序列化问题
查看>>
Html.Partial和Html. RenderPartial用法
查看>>
查看linux系统中占用cpu最高的语句
查看>>
[洛谷P1738]洛谷的文件夹
查看>>
Ubuntu server 16.04的安装 以及配置(服务器版)
查看>>
Jtest 对象库的使用(Object Repository)
查看>>
phpstudy的mysql版本升级至5.7
查看>>
ubuntu server设置时区和更新时间
查看>>
《弟子规》下的沉思
查看>>
B. Beautiful Paintings
查看>>
AtCoder Beginner Contest 103
查看>>
Codeforces 589F Gourmet and Banquet
查看>>