`

利用委托机制处理.NET中的异常

阅读更多

转自 terrylee.cnblogs.com

概述

在.NET中,可以轻松的通过try-catch块来捕获异常。为了防止在应用程序中出现未处理的异常,可以通过添加一个全局的异常处理函数,如果是多线程的处理,还必须考虑除了主线程之外的工作线程中的异常处理办法,这里用委托机制来实现。


主线程的异常处理

使用Application对象中的ThreadException属性设置一个delegate来捕获所有的未处理的主线程中出现的异常。注意这个全局异常处理程序,只能捕获到主线程中的异常,对于我们自己添加的工作线程、辅助线程的异常是捕获不到的。

在应用程序入口添加全局异常处理:
/// <summary>
/// 应用程序的主入口点。
/// </summary>
[STAThread]
static void Main()
{
    ///添加主线程的全局异常处理
    Application.ThreadException += new ThreadExceptionEventHandler(
        MainUIThreadExceptionHandler);

    Application.Run(new Form1());
}
 处理程序:
public static void MainUIThreadExceptionHandler(Exception ex)
{
    MainUIThreadExceptionHandler(null, new ThreadExceptionEventArgs(ex));
}

/// <summary>
/// 主线程全局异常信息的处理
/// </summary>
/// <param name="sender"></param>
/// <param name="t"></param>
public static void MainUIThreadExceptionHandler(object sender, ThreadExceptionEventArgs e)
{
    MessageBox.Show(
        "应用程序发生了如下的异常信息"
        + ":" + (char) 13
        + (char) 13 + e.Exception.Message
        + (char) 13 + (char) 13
        + "请于系统管理员取得联系!"
        + (char) 13 + (char) 13
        , "异常信息"
        , MessageBoxButtons.OK
        , MessageBoxIcon.Error
        , MessageBoxDefaultButton.Button1
        , MessageBoxOptions.ServiceNotification);
}
 工作线程的异常处理

编写多线程代码时,我们必须考虑在工作线程中出现的异常。在线程的入口使用try-catch块,并通过delegate将发生的异常通知给主线程。必须将异常信息通知主线程,否则应用程序不会报错,异常将会消失。

在线程入口使用try-catch块:
/// <summary>
/// 在线程的入口点加入try-catch块
/// </summary>
private void DataSave()
{
    try
    {
        CreateException();
    }
    catch (Exception e)
    {
        ///通过delegate转向工作线程的异常处理
        new WorkerThreadExceptionHandlerDelegate(
            WorkerThreadExceptionHandler).BeginInvoke(e
            , null
            , null);
    }
}
 工作线程异常的处理:
/// <summary>
/// 声明工作线程的delegate
/// </summary>
public delegate void WorkerThreadExceptionHandlerDelegate(Exception e);

/// <summary>
/// 工作线程的异常处理
/// </summary>
/// <param name="e"></param>
public void WorkerThreadExceptionHandler(Exception e)
{
    ///添加其他的处理代码

    ///通知全局异常处理程序
    MainUIThreadExceptionHandler(this, new ThreadExceptionEventArgs(e));
}
 总结

对于捕获到异常,我们可以Log到文件或者数据库,但是必须保证捕获到所有的异常,以上通过委托机制实现了.NET中的主线程以及工作线程中的异常捕获。

完整的程序代码:
using System;
using System.Threading;
using System.Windows.Forms;

namespace UseDelegateException
{
    /// <summary>
    /// 功能:利用Delegate实现异常的全局处理
    /// 编写:Terrylee
    /// 日期:2005年12月10日
    /// </summary>
    public class Form1 : System.Windows.Forms.Form
    {
        private System.Windows.Forms.Button btnMainUIThread;
        private System.Windows.Forms.Button btnWorkThread;
        /// <summary>
        /// 必需的设计器变量。
        /// </summary>
        private System.ComponentModel.Container components = null;

        public Form1()
        {
            //
            // Windows 窗体设计器支持所必需的
            //
            InitializeComponent();

            //
            // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
            //
        }

        /// <summary>
        /// 清理所有正在使用的资源。
        /// </summary>
        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                if (components != null)
                {
                    components.Dispose();
                }
            }
            base.Dispose(disposing);
        }
        #region Windows 窗体设计器生成的代码
        /// <summary>
        /// 设计器支持所需的方法 - 不要使用代码编辑器修改
        /// 此方法的内容。
        /// </summary>
        private void InitializeComponent()
        {
            this.btnMainUIThread = new System.Windows.Forms.Button();
            this.btnWorkThread = new System.Windows.Forms.Button();
            this.SuspendLayout();
            // 
            // btnMainUIThread
            // 
            this.btnMainUIThread.Location = new System.Drawing.Point(40, 72);
            this.btnMainUIThread.Name = "btnMainUIThread";
            this.btnMainUIThread.Size = new System.Drawing.Size(112, 48);
            this.btnMainUIThread.TabIndex = 0;
            this.btnMainUIThread.Text = "主线程异常";
            this.btnMainUIThread.Click += new System.EventHandler(this.btnMainUIThread_Click);
            // 
            // btnWorkThread
            // 
            this.btnWorkThread.Location = new System.Drawing.Point(240, 72);
            this.btnWorkThread.Name = "btnWorkThread";
            this.btnWorkThread.Size = new System.Drawing.Size(112, 48);
            this.btnWorkThread.TabIndex = 1;
            this.btnWorkThread.Text = "工作线程异常";
            this.btnWorkThread.Click += new System.EventHandler(this.btnWorkThread_Click);
            // 
            // Form1
            // 
            this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
            this.ClientSize = new System.Drawing.Size(392, 197);
            this.Controls.Add(this.btnWorkThread);
            this.Controls.Add(this.btnMainUIThread);
            this.MaximizeBox = false;
            this.Name = "Form1";
            this.Text = "Form1";
            this.ResumeLayout(false);
        }
        #endregion

        /// <summary>
        /// 应用程序的主入口点。
        /// </summary>
        [STAThread]
        static void Main()
        {
            ///添加主线程的全局异常处理
            Application.ThreadException += new ThreadExceptionEventHandler(
                MainUIThreadExceptionHandler);

            Application.Run(new Form1());
        }

        public static void MainUIThreadExceptionHandler(Exception ex)
        {
            MainUIThreadExceptionHandler(null, new ThreadExceptionEventArgs(ex));
        }

        /// <summary>
        /// 主线程全局异常信息的处理
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="t"></param>
        public static void MainUIThreadExceptionHandler(object sender, ThreadExceptionEventArgs e)
        {
            MessageBox.Show(
                "应用程序发生了如下的异常信息"
                + ":" + (char) 13
                + (char) 13 + e.Exception.Message
                + (char) 13 + (char) 13
                + "请于系统管理员取得联系!"
                + (char) 13 + (char) 13
                , "异常信息"
                , MessageBoxButtons.OK
                , MessageBoxIcon.Error
                , MessageBoxDefaultButton.Button1
                , MessageBoxOptions.ServiceNotification);
        }

        /// <summary>
        /// 声明工作线程的delegate
        /// </summary>
        public delegate void WorkerThreadExceptionHandlerDelegate(Exception e);

        /// <summary>
        /// 工作线程的异常处理
        /// </summary>
        /// <param name="e"></param>
        public void WorkerThreadExceptionHandler(Exception e)
        {
            ///添加其他的处理代码

            ///通知全局异常处理程序
            MainUIThreadExceptionHandler(this, new ThreadExceptionEventArgs(e));
        }
        /// <summary>
        /// 制造异常信息,这里抛出一个除0的异常
        /// </summary>
        private void CreateException()
        {
            int a = 1;
            int b = 0;

            int c;
            c = a / b;
        }

        /// <summary>
        /// 在线程的入口点加入try-catch块
        /// </summary>
        private void DataSave()
        {
            try
            {
                CreateException();
            }
            catch (Exception e)
            {
                ///通过delegate转向工作线程的异常处理
                new WorkerThreadExceptionHandlerDelegate(
                    WorkerThreadExceptionHandler).BeginInvoke(e
                    , null
                    , null);
            }
        }

        /// <summary>
        /// 发生主线程异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnMainUIThread_Click(object sender, System.EventArgs e)
        {
            ///这里出现一个异常,我们不予捕获,交由全局处理函数
            CreateException();
        }

        /// <summary>
        /// 发生工作线程异常
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void btnWorkThread_Click(object sender, System.EventArgs e)
        {
            Thread t = new Thread(new ThreadStart(DataSave));
            t.Start();
        }
    }
}
 
分享到:
评论

相关推荐

    asp.net知识库

    利用委托机制处理.NET中的异常 与正则表达式相关的几个小工具 你真的了解.NET中的String吗? .NET中的方法及其调用(一) 如何判断ArrayList,Hashtable,SortedList 这类对象是否相等 帮助解决网页和JS文件中的中文...

    C#开发常见问题清单总结与入门常见问题.docx

    1. 编程基础 技巧1:理解并有效使用命名空间和类 技巧2:构造函数的最佳实践与注意事项 技巧3:变量声明与初始化的规范化 技巧4:使用Nullable类型避免...技巧17:在Web API开发中处理CORS及安全性问题 技巧1

    net学习笔记及其他代码应用

    30.简要谈一下您对微软.NET 构架下remoting和webservice两项技术的理解以及实际中的应用。 答:WS主要是可利用HTTP,穿透防火墙。而Remoting可以利用TCP/IP,二进制传送提高效率。 31.公司要求开发一个继承System....

    JAVA_API1.6文档(中文)

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    JavaAPI1.6中文chm文档 part1

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    Java 1.6 API 中文 New

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    JavaAPI中文chm文档 part2

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    [Java参考文档].JDK_API 1.6

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    java api最新7.0

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    Visual C++ 2010入门经典(第5版)--源代码及课后练习答案

    6.3.3 MFC中的异常处理 255 6.4 处理内存分配错误 256 6.5 函数重载 257 6.5.1 函数重载的概念 258 6.5.2 引用类型和重载选择 260 6.5.3 何时重载函数 260 6.6 函数模板 261 6.7 使用decltype操作符 263 ...

    JDK_1_6 API

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    [Java参考文档]

    javax.transaction 包含解组期间通过 ORB 机制抛出的三个异常。 javax.transaction.xa 提供定义事务管理器和资源管理器之间的协定的 API,它允许事务管理器添加或删除 JTA 事务中的资源对象(由资源管理器驱动程序...

    RED HAT LINUX 6大全

    2.2.2 不利用引导软盘进行安装 7 2.2.3 虚拟控制台 7 2.2.4 对话框 7 2.3 一步步地安装 7 2.3.1 开始安装 7 2.3.2 内核参数选项 8 2.3.3 安装程序 9 2.3.4 选择一种安装方法 9 2.3.5 光盘安装 10 2.4 硬件配置 14 ...

Global site tag (gtag.js) - Google Analytics