【第一篇笔记】C# 全局容错,全局异常

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

方法一:

static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [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);
        }

        /// <summary>
        /// 生成自定义异常消息
        /// </summary>
        /// <param name="ex">异常对象</param>
        /// <param name="backStr">备用异常消息:当ex为null时有效</param>
        /// <returns>异常字符串文本</returns>
        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();
        }
    }

方法二:

转载于:王旭博客 » 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 构造函数
        /// <summary>
        /// Bug发送窗口
        /// </summary>
        /// <param name="bugInfo">Bug信息</param>
        public FrmBugReport(Exception bugInfo)
        {
            InitializeComponent();
            _bugInfo = bugInfo;
            this.txtBugInfo.Text = bugInfo.Message;
            lblErrorCode.Text = Guid.NewGuid().ToString();
        }

        /// <summary>
        /// Bug发送窗口
        /// </summary>
        /// <param name="bugInfo">Bug信息</param>
        /// <param name="errorCode">错误号</param>
        public FrmBugReport(Exception bugInfo, string errorCode)
        {
            InitializeComponent();
            _bugInfo = bugInfo;
            this.txtBugInfo.Text = bugInfo.Message;
            lblErrorCode.Text = errorCode;
        }
        #endregion

        #region 公开静态方法
        /// <summary>
        /// 提示Bug
        /// </summary>
        /// <param name="bugInfo">Bug信息</param>
        /// <param name="errorCode">错误号</param>
        public static void ShowBug(Exception bugInfo, string errorCode)
        {
            new FrmBugReport(bugInfo, errorCode).ShowDialog();
        }

        /// <summary>
        /// 提示Bug
        /// </summary>
        /// <param name="bugInfo">Bug信息</param>
        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);
        }

    }
}

这个项目就完成了。

3.2 构建异常测试程序

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

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

using System;
using System.Collections.Generic;
using System.Windows.Forms;

namespace WinformTest
{
    static class Program
    {
        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [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了,还算非常简单的,只是可能我长篇大论了。哈..下次尽量简短..现在应该掌握了对异常的合理处理了吧。

该解决方案的源码下载:WinformException

小知识:如何处理多线程中的异常,让程序不会强制退出。
你可以这样,把多线程中的任务全部try起来。

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

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

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

时间: 2024-10-22 16:45:49

【第一篇笔记】C# 全局容错,全局异常的相关文章

c#第一篇笔记---关于list

-> List<T> 线性集合,长度可变的数组 -> 增 Add() AddRange() Insert() 添加一个元素list.Add("张三"); 添加一组元素 string[] temArr={"张三","李四","王五"}; list.AddRange(temArr); 插入一个元素 list.Insert(1,"插入元素"); -> 删 Remove(T) Remo

第一篇~笔记

怎么说呢 毕竟第一次写这种东西 还是写个开栏语吧 专业是计算机应用与技术,但是鄙人爱好不限于此 喜欢艺术 我也不知道写啥子嘛 反正写了也没人看,看了的也不一定关注, 关注了的也不一定喜欢我 就写一些个人笔记吧 就这样吧 原文地址:https://www.cnblogs.com/xpblog/p/8443437.html

ms project(第一篇笔记)

http://v.youku.com/v_show/id_XNzY0Nzg5MjY0.html?from=s1.8-1-1.2 http://wenku.baidu.com/view/7bb17abc1a37f111f1855be7.html WBS(Work Breakdown Structure 工作分解结构) 与项目团队成员一起制作. 几个关键事件: 1. 确定所有任务 2. 确定一个大概的任务工期 原则: 完成这两个事件,需要项目经理与项目成员一起分工与配合,协商完成 1. 列出所有任务

20170525第一篇笔记学习方法

Django 框架下的Blog 搭建 ---第一篇笔记

1.安装python 2.x 版本并加入环境变量 2.安装 virtualevn 工具将系统隔离成一个个虚拟docker 参考:https://pypi.python.org/pypi/virtualenv 2.1 mkdir 一个文件夹,并用 virtualenv  文件夹名, 虚拟一个带 setuptools 等工具的 python 环境 2.2 用 bin 目录下的工具 pip 进行安装Django    ./pip install Django==1.9.6  参考:https://do

Eclipse插件开发 学习笔记 PDF 第一篇到第四篇 免分下载 开发基础 核心技术 高级进阶 综合实例

<<Eclipse插件开发 学习笔记>>,本书由浅入深.有重点.有针对性地介绍了Eclipse插件开发技术,全书分为4篇共24章.第一篇介绍Eclipse平台界面开发的基础知识.包含SWT控件的使用.界面布局.事件处理等内容:第二篇是插件开发核心技术,主要介绍插件开发的核心知识要点,包含行为(Action).视图(ViewPart).编辑器(Editor).透视图(Perspective)等10章的内容.第三篇主要讲述插件开发的高级内容,包含开发高级内容.富client平台技术(R

C# 基础笔记(第一篇)

C#基础 概念:.net与c#.net/dontnet:一般指.net framework框架,一种平台,一种技术c#(charp):一种编程语言,可以开发基于.net的应用. *java既是一种技术又是一种编程语言.                           .net都能干什么?开发桌面应用程序   Winforminternet应用程序    Asp.net/webservice C/S:客户机(Client)/服务器模式(Server)B/S:浏览器(Browser)/务器模式(

《javascript权威指南》读书笔记——第一篇

<javascript权威指南>读书笔记--第一篇 金刚 javascript js javascript权威指南 由于最近想系统学习下javascript,所以开始在kindle上看这本书来补充下. 今天是今年的196天,由于我之前承诺过,每天分享读书笔记,只是之前分享的是大众读物,所以随手分享到kindle阅读群里了.但是现在读的是技术类书籍,分享到kindle读书群不太合适,所以还是以博客的形式分享.这样子,一个链接,大家感兴趣了就点开看看,不感兴趣了,就不点开. 其实这篇文章应该是昨天

0807&mdash;MapReduce的第一篇学习笔记

http://blog.csdn.net/v_july_v/article/details/6637014 1 2 3 4 0807—MapReduce的第一篇学习笔记