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

在.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 System.Threading.
        ThreadExceptionEventArgs(e));
}

总结

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


完整的程序代码:


using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;

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 );
        }

        Windows 窗体设计器生成的代码#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 System.Threading.
                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();
        }
    }
}

你可能感兴趣的:(多线程,.net,windows,工作,制造)