概述

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


主线程的异常处理

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

在应用程序入口添加全局异常处理:


利用委托机制处理.NET中的异常(引用)_工作线程  static void Main()
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_05            Application.ThreadException += new ThreadExceptionEventHandler(Form1.MainUIThreadExceptionHandler);
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_05            //Application.EnableVisualStyles();
利用委托机制处理.NET中的异常(引用)_异常处理_05            //Application.SetCompatibleTextRenderingDefault(false);
利用委托机制处理.NET中的异常(引用)_异常处理_05            //Application.Run(new Form1());
利用委托机制处理.NET中的异常(引用)_异常处理_05            System.Windows.Forms.Application.Run(new Form1());
利用委托机制处理.NET中的异常(引用)_异常处理_12        }
利用委托机制处理.NET中的异常(引用)_工作线程

处理程序:

利用委托机制处理.NET中的异常(引用)_工作线程  public static void MainUIThreadExceptionHandler(Exception ex)
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            MainUIThreadExceptionHandler(null, new ThreadExceptionEventArgs(ex));
利用委托机制处理.NET中的异常(引用)_异常处理_12        }
利用委托机制处理.NET中的异常(引用)_工作线程  public static void MainUIThreadExceptionHandler(object sender, ThreadExceptionEventArgs e)
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            MessageBox.Show(
利用委托机制处理.NET中的异常(引用)_异常处理_05            "应用程序发生了如下的异常信息"
利用委托机制处理.NET中的异常(引用)_异常处理_05            + ":" + (char)13
利用委托机制处理.NET中的异常(引用)_异常处理_05            + (char)13 + e.Exception.Message
利用委托机制处理.NET中的异常(引用)_异常处理_05            + (char)13 + (char)13
利用委托机制处理.NET中的异常(引用)_异常处理_05            + "请于系统管理员取得联系!"
利用委托机制处理.NET中的异常(引用)_异常处理_05            + (char)13 + (char)13
利用委托机制处理.NET中的异常(引用)_异常处理_05            , "异常信息"
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxButtons.OK
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxIcon.Error
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxDefaultButton.Button1
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxOptions.ServiceNotification);
利用委托机制处理.NET中的异常(引用)_异常处理_12        }
利用委托机制处理.NET中的异常(引用)_工作线程

 

工作线程的异常处理

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

在线程入口使用try-catch块:

 

利用委托机制处理.NET中的异常(引用)_工作线程  private void DataSave()
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            try
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05                CreateException();
利用委托机制处理.NET中的异常(引用)_异常处理_47            }
利用委托机制处理.NET中的异常(引用)_异常处理_05            catch (Exception e)
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44                /**//**/
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44                /**////通过delegate转向工作线程的异常处理
利用委托机制处理.NET中的异常(引用)_异常处理_05                new WorkerThreadExceptionHandlerDelegate(WorkerThreadExceptionHandler).BeginInvoke(e, null, null);
利用委托机制处理.NET中的异常(引用)_异常处理_47            }
利用委托机制处理.NET中的异常(引用)_异常处理_12        }

 

工作线程异常的处理:

利用委托机制处理.NET中的异常(引用)_工作线程public delegate void WorkerThreadExceptionHandlerDelegate(Exception e);
利用委托机制处理.NET中的异常(引用)_工作线程    public void WorkerThreadExceptionHandler(Exception e)
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            /**//**/
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            /**////添加其他的处理代码
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_47            ///通知全局异常处理程序
利用委托机制处理.NET中的异常(引用)_异常处理_05            MainUIThreadExceptionHandler(
利用委托机制处理.NET中的异常(引用)_异常处理_05                this, new System.Threading.
利用委托机制处理.NET中的异常(引用)_异常处理_05                ThreadExceptionEventArgs(e));
利用委托机制处理.NET中的异常(引用)_异常处理_12        }

 

总结

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

 

完整的程序代码:

主文件:
利用委托机制处理.NET中的异常(引用)_工作线程using System;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Collections.Generic;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Windows.Forms;
利用委托机制处理.NET中的异常(引用)_工作线程
利用委托机制处理.NET中的异常(引用)_工作线程using System.Threading;
利用委托机制处理.NET中的异常(引用)_工作线程
利用委托机制处理.NET中的异常(引用)_工作线程namespace WindowsApplication2
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05    static class Program
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44    利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_05       
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        /**//// <summary>
利用委托机制处理.NET中的异常(引用)_异常处理_05        /// 应用程序的主入口点。
利用委托机制处理.NET中的异常(引用)_异常处理_47        /// </summary>
利用委托机制处理.NET中的异常(引用)_异常处理_05        [STAThread]
利用委托机制处理.NET中的异常(引用)_异常处理_05        static void Main()
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_05            Application.ThreadException += new ThreadExceptionEventHandler(Form1.MainUIThreadExceptionHandler);
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_05            //Application.EnableVisualStyles();
利用委托机制处理.NET中的异常(引用)_异常处理_05            //Application.SetCompatibleTextRenderingDefault(false);
利用委托机制处理.NET中的异常(引用)_异常处理_05            //Application.Run(new Form1());
利用委托机制处理.NET中的异常(引用)_异常处理_05            System.Windows.Forms.Application.Run(new Form1());
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_05       
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_47    }
利用委托机制处理.NET中的异常(引用)_异常处理_12}

Form1.cs文件:
利用委托机制处理.NET中的异常(引用)_工作线程using System;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Collections.Generic;
利用委托机制处理.NET中的异常(引用)_工作线程using System.ComponentModel;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Data;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Drawing;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Text;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Windows.Forms;
利用委托机制处理.NET中的异常(引用)_工作线程using System.Threading;
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03/**////线程的异常处理
利用委托机制处理.NET中的异常(引用)_工作线程namespace WindowsApplication2
利用委托机制处理.NET中的异常(引用)_异常处理_02利用委托机制处理.NET中的异常(引用)_应用程序_03利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05    public partial class Form1 : Form
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44    利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05        public delegate void WorkerThreadExceptionHandlerDelegate(Exception e);
利用委托机制处理.NET中的异常(引用)_异常处理_05        public Form1()
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            InitializeComponent();
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_05        public static void MainUIThreadExceptionHandler(Exception ex)
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            MainUIThreadExceptionHandler(null, new ThreadExceptionEventArgs(ex));
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_05        public static void MainUIThreadExceptionHandler(object sender, ThreadExceptionEventArgs e)
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            MessageBox.Show(
利用委托机制处理.NET中的异常(引用)_异常处理_05            "应用程序发生了如下的异常信息"
利用委托机制处理.NET中的异常(引用)_异常处理_05            + ":" + (char)13
利用委托机制处理.NET中的异常(引用)_异常处理_05            + (char)13 + e.Exception.Message
利用委托机制处理.NET中的异常(引用)_异常处理_05            + (char)13 + (char)13
利用委托机制处理.NET中的异常(引用)_异常处理_05            + "请于系统管理员取得联系!"
利用委托机制处理.NET中的异常(引用)_异常处理_05            + (char)13 + (char)13
利用委托机制处理.NET中的异常(引用)_异常处理_05            , "异常信息"
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxButtons.OK
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxIcon.Error
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxDefaultButton.Button1
利用委托机制处理.NET中的异常(引用)_异常处理_05            , MessageBoxOptions.ServiceNotification);
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        /**//**/
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        /**//// <summary>
利用委托机制处理.NET中的异常(引用)_异常处理_05        /// 制造异常信息,这里抛出一个除0的异常
利用委托机制处理.NET中的异常(引用)_异常处理_47        /// </summary>
利用委托机制处理.NET中的异常(引用)_异常处理_05        private void CreateException()
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            int a = 1;
利用委托机制处理.NET中的异常(引用)_异常处理_05            int b = 0;
利用委托机制处理.NET中的异常(引用)_异常处理_05            int c;
利用委托机制处理.NET中的异常(引用)_异常处理_05            c = a / b;
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_05        private void DataSave()
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            try
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05                CreateException();
利用委托机制处理.NET中的异常(引用)_异常处理_47            }
利用委托机制处理.NET中的异常(引用)_异常处理_05            catch (Exception e)
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44                /**//**/
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44                /**////通过delegate转向工作线程的异常处理
利用委托机制处理.NET中的异常(引用)_异常处理_05                new WorkerThreadExceptionHandlerDelegate(WorkerThreadExceptionHandler).BeginInvoke(e, null, null);
利用委托机制处理.NET中的异常(引用)_异常处理_47            }
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_05        public void WorkerThreadExceptionHandler(Exception e)
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            /**//**/
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44            /**////添加其他的处理代码
利用委托机制处理.NET中的异常(引用)_异常处理_05
利用委托机制处理.NET中的异常(引用)_异常处理_47            ///通知全局异常处理程序
利用委托机制处理.NET中的异常(引用)_异常处理_05            MainUIThreadExceptionHandler(
利用委托机制处理.NET中的异常(引用)_异常处理_05                this, new System.Threading.
利用委托机制处理.NET中的异常(引用)_异常处理_05                ThreadExceptionEventArgs(e));
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_05        private void btnMainUIThread_Click(object sender, EventArgs e)
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            CreateException();
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_05        private void btnWorkThread_Click(object sender, EventArgs e)
利用委托机制处理.NET中的异常(引用)_异常处理_43利用委托机制处理.NET中的异常(引用)_工作线程_44        利用委托机制处理.NET中的异常(引用)_应用程序_04{
利用委托机制处理.NET中的异常(引用)_异常处理_05            Thread t = new Thread(new ThreadStart(DataSave));
利用委托机制处理.NET中的异常(引用)_异常处理_05            t.Start();
利用委托机制处理.NET中的异常(引用)_异常处理_47        }
利用委托机制处理.NET中的异常(引用)_异常处理_47    }
利用委托机制处理.NET中的异常(引用)_异常处理_12}