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

概述

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

主线程的异常处理

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

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

 1/// <summary>
 2        /// 应用程序的主入口点。
 3        /// </summary>
 4        [STAThread]
 5        static void Main() 
 6        {    
 7            ///添加主线程的全局异常处理
 8            Application.ThreadException += new 
 9                ThreadExceptionEventHandler(
10                MainUIThreadExceptionHandler);
11
12            Application.Run(new Form1());
13        }

处理程序:

 1public static void MainUIThreadExceptionHandler(Exception ex)
 2{
 3    MainUIThreadExceptionHandler(null, new
 4        ThreadExceptionEventArgs(ex));
 5}
 6
 7/// <summary>
 8/// 主线程全局异常信息的处理
 9/// </summary>
10/// <param name="sender"></param>
11/// <param name="t"></param>
12public static void MainUIThreadExceptionHandler(object
13    sender, ThreadExceptionEventArgs e)
14{
15    MessageBox.Show(
16        "应用程序发生了如下的异常信息"
17        + ":" + (char)13
18        + (char)13 + e.Exception.Message
19        + (char)13 + (char)13
20        + "请于系统管理员取得联系!"
21        + (char)13 + (char)13
22        , "异常信息"
23        , MessageBoxButtons.OK
24        , MessageBoxIcon.Error
25        , MessageBoxDefaultButton.Button1 
26        , MessageBoxOptions.ServiceNotification);        
27}

工作线程的异常处理

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

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

 1/// <summary>
 2/// 在线程的入口点加入try-catch块
 3/// </summary>
 4private void DataSave()
 5{
 6    try
 7    {
 8        CreateException();
 9    }
10    catch(Exception e)
11    {
12        ///通过delegate转向工作线程的异常处理
13        new WorkerThreadExceptionHandlerDelegate(
14            WorkerThreadExceptionHandler).BeginInvoke(e
15            ,null
16            ,null);
17    }
18}

工作线程异常的处理:

 1/// <summary>
 2/// 声明工作线程的delegate
 3/// </summary>
 4public delegate void
 5    WorkerThreadExceptionHandlerDelegate(Exception e);
 6
 7/// <summary>
 8/// 工作线程的异常处理
 9/// </summary>
10/// <param name="e"></param>
11public void WorkerThreadExceptionHandler(Exception e)
12{
13    ///添加其他的处理代码
14
15    ///通知全局异常处理程序
16    MainUIThreadExceptionHandler(
17        this, new System.Threading.
18        ThreadExceptionEventArgs(e));
19}

总结

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

完整的程序代码:

  1using System;
  2using System.Drawing;
  3using System.Collections;
  4using System.ComponentModel;
  5using System.Windows.Forms;
  6using System.Data;
  7using System.Threading;
  8
  9namespace UseDelegateException
 10{
 11    /// <summary>
 12    /// 功能:利用Delegate实现异常的全局处理
 13    /// 编写:Terrylee
 14    /// 日期:2005年12月10日
 15    /// </summary>
 16    public class Form1 : System.Windows.Forms.Form
 17    {
 18        private System.Windows.Forms.Button btnMainUIThread;
 19        private System.Windows.Forms.Button btnWorkThread;
 20        /// <summary>
 21        /// 必需的设计器变量。
 22        /// </summary>
 23        private System.ComponentModel.Container components = null;
 24
 25        public Form1()
 26        {
 27            //
 28            // Windows 窗体设计器支持所必需的
 29            //
 30            InitializeComponent();
 31
 32            //
 33            // TODO: 在 InitializeComponent 调用后添加任何构造函数代码
 34            //
 35        }
 36
 37        /// <summary>
 38        /// 清理所有正在使用的资源。
 39        /// </summary>
 40        protected override void Dispose( bool disposing )
 41        {
 42            if( disposing )
 43            {
 44                if (components != null) 
 45                {
 46                    components.Dispose();
 47                }
 48            }
 49            base.Dispose( disposing );
 50        }
 51
 52        Windows 窗体设计器生成的代码 Windows 窗体设计器生成的代码
 53        /// <summary>
 54        /// 设计器支持所需的方法 - 不要使用代码编辑器修改
 55        /// 此方法的内容。
 56        /// </summary>
 57        private void InitializeComponent()
 58        {
 59            this.btnMainUIThread = new System.Windows.Forms.Button();
 60            this.btnWorkThread = new System.Windows.Forms.Button();
 61            this.SuspendLayout();
 62            // 
 63            // btnMainUIThread
 64            // 
 65            this.btnMainUIThread.Location = new System.Drawing.Point(40, 72);
 66            this.btnMainUIThread.Name = "btnMainUIThread";
 67            this.btnMainUIThread.Size = new System.Drawing.Size(112, 48);
 68            this.btnMainUIThread.TabIndex = 0;
 69            this.btnMainUIThread.Text = "主线程异常";
 70            this.btnMainUIThread.Click += new System.EventHandler(this.btnMainUIThread_Click);
 71            // 
 72            // btnWorkThread
 73            // 
 74            this.btnWorkThread.Location = new System.Drawing.Point(240, 72);
 75            this.btnWorkThread.Name = "btnWorkThread";
 76            this.btnWorkThread.Size = new System.Drawing.Size(112, 48);
 77            this.btnWorkThread.TabIndex = 1;
 78            this.btnWorkThread.Text = "工作线程异常";
 79            this.btnWorkThread.Click += new System.EventHandler(this.btnWorkThread_Click);
 80            // 
 81            // Form1
 82            // 
 83            this.AutoScaleBaseSize = new System.Drawing.Size(6, 14);
 84            this.ClientSize = new System.Drawing.Size(392, 197);
 85            this.Controls.Add(this.btnWorkThread);
 86            this.Controls.Add(this.btnMainUIThread);
 87            this.MaximizeBox = false;
 88            this.Name = "Form1";
 89            this.Text = "Form1";
 90            this.ResumeLayout(false);
 91
 92        }
 93        #endregion
 94
 95        /// <summary>
 96        /// 应用程序的主入口点。
 97        /// </summary>
 98        [STAThread]
 99        static void Main() 
100        {    
101            ///添加主线程的全局异常处理
102            Application.ThreadException += new 
103                ThreadExceptionEventHandler(
104                MainUIThreadExceptionHandler);
105
106            Application.Run(new Form1());
107        }
108        
109        public static void MainUIThreadExceptionHandler(Exception ex)
110        {
111            MainUIThreadExceptionHandler(null, new
112                ThreadExceptionEventArgs(ex));
113        }
114
115        /// <summary>
116        /// 主线程全局异常信息的处理
117        /// </summary>
118        /// <param name="sender"></param>
119        /// <param name="t"></param>
120        public static void MainUIThreadExceptionHandler(object
121            sender, ThreadExceptionEventArgs e)
122        {
123            MessageBox.Show(
124                "应用程序发生了如下的异常信息"
125                + ":" + (char)13
126                + (char)13 + e.Exception.Message
127                + (char)13 + (char)13
128                + "请于系统管理员取得联系!"
129                + (char)13 + (char)13
130                , "异常信息"
131                , MessageBoxButtons.OK
132                , MessageBoxIcon.Error
133                , MessageBoxDefaultButton.Button1 
134                , MessageBoxOptions.ServiceNotification);        
135        }
136        
137        /// <summary>
138        /// 声明工作线程的delegate
139        /// </summary>
140        public delegate void
141            WorkerThreadExceptionHandlerDelegate(Exception e);
142
143        /// <summary>
144        /// 工作线程的异常处理
145        /// </summary>
146        /// <param name="e"></param>
147        public void WorkerThreadExceptionHandler(Exception e)
148        {
149            ///添加其他的处理代码
150
151            ///通知全局异常处理程序
152            MainUIThreadExceptionHandler(
153                this, new System.Threading.
154                ThreadExceptionEventArgs(e));
155        }
156        /// <summary>
157        /// 制造异常信息,这里抛出一个除0的异常
158        /// </summary>
159        private void CreateException()
160        {
161            int a = 1;
162            int b = 0;
163
164            int c;
165            c = a/b;
166        }
167        
168        /// <summary>
169        /// 在线程的入口点加入try-catch块
170        /// </summary>
171        private void DataSave()
172        {
173            try
174            {
175                CreateException();
176            }
177            catch(Exception e)
178            {
179                ///通过delegate转向工作线程的异常处理
180                new WorkerThreadExceptionHandlerDelegate(
181                    WorkerThreadExceptionHandler).BeginInvoke(e
182                    ,null
183                    ,null);
184            }
185        }
186
187        /// <summary>
188        /// 发生主线程异常
189        /// </summary>
190        /// <param name="sender"></param>
191        /// <param name="e"></param>
192        private void btnMainUIThread_Click(object sender, System.EventArgs e)
193        {
194            ///这里出现一个异常,我们不予捕获,交由全局处理函数
195            CreateException();
196        }
197        
198        /// <summary>
199        /// 发生工作线程异常
200        /// </summary>
201        /// <param name="sender"></param>
202        /// <param name="e"></param>
203        private void btnWorkThread_Click(object sender, System.EventArgs e)
204        {
205            Thread t = new Thread( new ThreadStart(DataSave));
206            t.Start();
207        }
208    }
209}
210

转载自: http://terrylee.cnblogs.com/archive/2005/12/12/295243.html

转载于:https://www.cnblogs.com/AdmiralSoft/archive/2008/01/28/1056627.html

多线程异常处理【转】相关推荐

  1. 异常处理器详解 Java多线程异常处理机制 多线程中篇(四)

    在Thread中有异常处理器相关的方法 在ThreadGroup中也有相关的异常处理方法 示例 未检查异常 对于未检查异常,将会直接宕掉,主线程则继续运行,程序会继续运行 在主线程中能不能捕获呢? 我 ...

  2. 异步多线程(五)多线程异常处理

    异步多线程(五)多线程异常处理 参考文章: (1)异步多线程(五)多线程异常处理 (2)https://www.cnblogs.com/JohnTang/p/11010357.html (3)http ...

  3. java多线程 异常处理_Java8多线程ForkJoinPool:处理异常

    java多线程 异常处理 引入Java8 lambda背后的主要动机之一是能够尽可能轻松地使用多核的能力(请参阅精通Lambdas:多核世界中的Java编程 ). 只需将代码从collection.s ...

  4. Java 异常处理(标准抛异常、异常处理、多异常、Finally、多线程异常处理、获取异常的堆栈信息、链试异常、自定义异常)

    使用 catch 处理异常(标准抛异常) public class Main {public static void main (String args[]) {int array[]={20,20, ...

  5. .NET异步和多线程系列(四)- 多线程异常处理、线程取消、多线程的临时变量问题、线程安全和锁lock

    本文是.NET异步和多线程系列第四章,主要介绍的是多线程异常处理.线程取消.多线程的临时变量问题.线程安全和锁lock等. 一.多线程异常处理 多线程里面抛出的异常,会终结当前线程,但是不会影响别的线 ...

  6. Java多线程异常处理

    在java多线程程序中,所有线程都不允许抛出未捕获的checked exception,也就是说各个线程需要自己把自己的checked exception处理掉.这一点是通过java.lang.Run ...

  7. 多线程异常处理:挖掘页面空窗背后的原因

    作为一名应用开发,大家是否有遇到以下现象,为什么一套非常优秀的兜底机制还是会出现页面空窗现象?本文将会通过实例和大家分享,作者在线程池使用过程中遇到的问题:异常处理,以及下线程池的参数设置经验. 什么 ...

  8. 博客园 noteless 全部文章 目录索引

    计算机发展历史 计算机发展阶段 计算机组成-数字逻辑电路 操作系统简单介绍 计算机启动过程的简单介绍 计算机发展个人理解-电路终究是电路 计算机语言的发展 计算机网络发展了解 计算机网络起源 网络发展 ...

  9. JAVA Thread线程异常监控

    一.场景描述:单线程程序可以用try...catch捕获程序的异常,而在多线程程序的时候是无法使用try...catch捕获. 示例1:多线程发生异常,无法使用try...catch捕获问题 publ ...

  10. java线程 对文件copy 可能删除了 报异常_java线程对文件copy可能删除了报异常

    篇一:java中多线程操作文件的复制及剪切 方法,重命名此抽象路径名表示的文件.相当于剪切并且重命名.但是此方法是与平台相关的,重命名操作无法将一个文件从一个文件系统移动到另外一个文件系统.这是导致文 ...

最新文章

  1. 2017.4.6AM
  2. Self-training在目标检测任务上的实践
  3. margin塌陷问题
  4. Oracle 练习P297 131026 PL/SQL块程序
  5. ORACLE 数据同步时,批量进行新增和更新操作的SQL写法
  6. spring 监听器
  7. Python(PyCharm)的下载安装汉化(2022)
  8. hive三种建表语句
  9. 日本企业家稻盛和夫的思想智慧
  10. 封装jquery的方法
  11. 斗鱼爬取主播相册爬虫函数封装
  12. HTML入门网页制作,HTML+css运用做出
  13. 【论】A Deep Reinforcement Learning Framework for Rebalancing Dockless Bike Sharing Systems
  14. From Seeing to Moving: A Survey on Learning for Visual Indoor Navigation (VIL)
  15. dz邮箱验证怎么设置_详细步骤!Discuz如何设置通过 SOCKET 连接 SMTP 服务器发送(支持 ESMTP 验证)实现论坛邮箱验证功能...
  16. 2021年3月20日美团笔试
  17. 微信小程序支付(基于Java实现微信JSAPI支付):支付,提现,退款
  18. 挖掘潜力谋发展优信二手车创新脚步与时俱进不停歇
  19. APS食品行业生产计划排程解决方案
  20. 中国移动企业短信通平台EMPP协议分析

热门文章

  1. Capture One mac版如何导入Lightroom目录
  2. git submodule使用的笔记
  3. 设计模式的征途—7.适配器(Adapter)模式
  4. 解决:PHP Deprecated: Comments starting with '#' are deprecated in ……
  5. 50余家光伏企业竞标混战:0.52元最低价仍有利润!
  6. Expressbody-parser
  7. Swing的Look And Feel机制研究
  8. ospf 几种LSA类型的总结
  9. 推荐腾讯最新重磅开源项目!
  10. 阿里十大最受开发者欢迎的工具!