异常处理最佳实践

关于异常处理的最佳实践:

1.所谓人无完人,咱们再写程序的时候不可能手动的try catch住所有的异常,那么对于没有catch住的异常怎么办,还好.net 提供了一个全局的事件用来handle住全局的异常

****对控制台程序而言****************************************

AppDomain.CurrentDomain.UnhandledException +=  new UnhandledExceptionEventHandler(UnhandledExceptionEventHandler);

异常处理方式委托到自己定义的方法

static void UnhandledExceptionEventHandler(object sender, UnhandledExceptionEventArgs e)  {
            try {
 
                using (System.IO.FileStream fs = new System.IO.FileStream(@"c:\testme.log",
 
System.IO.FileMode.Append, System.IO.FileAccess.Write))   {
 
                        using (System.IO.StreamWriter w = new System.IO.StreamWriter(fs,
 
                         System.Text.Encoding.UTF8))   {
                            w.WriteLine(e.ExceptionObject);
                       }   }   }
            catch     {}
        }

****对于winform有如下的处理方式*****************************************************

static void Main() {    
    //应用程序的主入口点添加ThreadException的事件处理。
    Application.ThreadException += new ThreadExceptionEventHandler(Application_ThreadException);    
}

 

未捕获异常会产生ThreadException 事件,下面是事件的处理函数

static void Application_ThreadException(object sender, ThreadExceptionEventArgs e) {
    //作为示例,这里用消息框显示异常的信息
    MessageBox.Show(e.Exception.Message,"异常",MessageBoxButtons.OK,MessageBoxIcon.Error);
}

 

****asp.net程序稍微有点复杂********************************

一般情况下产生的异常都不会导致asp.net程序终止,只是报个错而已,这是因为,asp.net程序实际上是在后台线程或线程池中运行,产生异常不会致使主线程终止,可以理解为后台产生异常后由asp.net框架自身捕获,处理方式是生成一个黄黄的页面,并且将异常信息以html的格式排列在上面。

那么我们怎么获得这个异常呢,很简单用Server.GetLastError()就能得到这个异常,通常在asp.net的Global.asax文件中提供一个方法Application_Error被委托到异常产生的事件上,我们可以在这里处理全局的未handle的异常,比方说记录到日志 Server.Transfer("")到一个更友好的页面

同学们表示,难道没有异常能直接导致asp.net程序的崩溃,W3WP.exe进程终止?这是必然有的,只要有可以运行的程序,必然有导致其运行不了的状况,那么遇到这种情况该怎么办呢?我怎么捕获这类异常呢?

来先创建一个HttpModule

public class UnhandledExceptionModule : IHttpModule {
        static object _initLock = new object();
        static bool _initialized = false;
 
        public UnhandledExceptionModule() {
            //
            // TODO: Add constructor logic here
            //
        }
 
        void OnUnhandledException(object o, UnhandledExceptionEventArgs e) {
            //Do some thing you wish to do when the Unhandled Exception raised.
            try {
                using (System.IO.FileStream fs = new System.IO.FileStream(@"c:\testme.log",
                        System.IO.FileMode.Append, System.IO.FileAccess.Write)) {
                    using (System.IO.StreamWriter w = new System.IO.StreamWriter(fs, System.Text.Encoding.UTF8)) {
                        w.WriteLine(e.ExceptionObject);
                    }
                }
            } catch {
            }
        }
 
 
        #region IHttpModule Members
 
        public void Dispose() {
            throw new Exception("The method or operation is not implemented.");
        }
 
        public void Init(HttpApplication context) {
            // Do this one time for each AppDomain.
            lock (_initLock) {
                if (!_initialized) {
                    AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(OnUnhandledException);
                    _initialized = true;
                }
            }
        }
        #endregion
    }

然后在web.config中注册一下下这个handle,在<system.web>节点中

<httpModules>
         <add name="UnhandledExceptionModule" type="WebMonitor.UnhandledExceptionModule" />
     </httpModules>

****上面说了系统抛出的异常,那么我们在做程序的时候要抛出异常怎么办********************

因为现在在写服务端程序的时候,不可能像以前一样返回错误代码,反正大家都认为这种方式不好,而改用遇到错误抛异常出去的方式,客户端程序调用我这个方法注意catch一下就行了,那么我找了半天,发现.net框架里面没有适合我这个异常的异常类,比方说做一个男人类,里面有一个方法叫拉屎,需要接受一个参数叫厕所,然后要判断一下这厕所是男厕还是女厕,是女厕得抛出异常,怎么样.net 不可能有这个异常类吧,处理方式如下,很简单,不解释。

 

public class SexError:Exception {
        public SexError() : base("你很2") {
        }
        public SexError(string message)
            : base(message) {
        }
 
        public SexError(string message,Exception innerException)
            : base(message, innerException) {
        }
    }

使用:

public class Man {
        public void HappyThing(Tolitle _tl) {
            if (_tl.Sex == "TrueMan") {
                throw new SexError();
                //throw new SexError("大流氓");
            }
        }
    }
 
    public class Tolitle {
        public string Sex { get; set; }
    }
 
    public class ManTolitle : Tolitle {
        public ManTolitle() {
            Sex = "TrueMan";
        }
    }

客户端调用

public class ClientApp{
        public void clientMethod() {
            Tolitle _tolitle = new ManTolitle();
            Man _FoolMan = new Man();
            try {
                _FoolMan.HappyThing(_tolitle);
            } catch (SexError ex) {
                showmessage("强烈谴责楼主去女厕不带我们");
 
     throw;
               //thow ex;         
 
        }
    }

最后说一下 throw和thow ex; 区别,广大同学比较喜欢用thow ex这个很不好的方式,他把原始异常信息截断了,包装成了新的异常,表现具体是堆栈信息显示是调用抛出异常的方法的栈信息,而不是直接是抛出异常产生处的栈信息,在堆栈最下面会显示个【外部方法】,灰色的,点不了所以不能准确判断异常的信息。

总之如果要继续上抛异常用throw好过throw catch住的异常

多线程异常,只要理解跨线程调用,很容易找到方法,先handle住全局异常

Application.ThreadException += new ThreadExceptionEventHandler( MainUIThreadExceptionHandler);

自己定义处理方法

public static void MainUIThreadExceptionHandler(Exception ex)
 {
      MainUIThreadExceptionHandler(null, new
      ThreadExceptionEventArgs(ex));
 }
 
//不要鸡冻 只是上面的重载形式
 
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);       
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值