C#自定义异常处理及写入日志

开发 后端
本文将介绍C#自定义异常处理及写入日志,System.ApplicationException 类是第三方定义的异常类,如果我们要自定义异常类,那么就应派生于它。

我们要站在异常一定可能会发生的角度来编写C#自定义异常处理程序,应对程序有可能发生的错误建立一个良好的C#自定义异常处理策略。

在做C#自定义异常处理的时候,最好能在应用程序所有的入口处(事件处理函数,主函数,线程入口)使用try-catch。但是不要在程序构造函数入口处添加try-catch,因为此处产生异常,它自己并没有能力来处理,因为它还没有构造完毕,只能再向外层抛出异常。

但我们也不能盲目使用异常。而且使用异常,可能会在一定程度上影响到程序的性能(C#中使用异常一般不影响性能)。

  1. //自定义异常类  
  2. publicclassMyException:ApplicationException  
  3. {  
  4. publicMyException(stringmessage):base(message)  
  5. {  
  6. }  
  7.  
  8. publicMyException(stringmessage,ExceptioninnerException)  
  9. :base(message,innerException)  
  10. {  
  11. }  

全局异常处理、多线程中的异常处理
将全局异常处理函数的委托加入到Application.ThreadException中,实现全局异常处理,但它只能处理主线程中未捕获的异常。在多线程异常处理时,工作线程/辅线程中产生异常,可以把它转给主线程来完成异常处理。如果线程之间不通知,是无法直接捕捉异常的。若没有去处理工作线程/辅线程中产生的异常,该异常将会“消失”掉。

为什么要把异常处理都交给主线程去做呢?举个例子:在WinForm里我们使用多线程来处理界面元素,一旦有异常发生就将异常消息显示出来。那么,是直接在异常发生后就MessageBox,还是将消息交给MainUI来统一显示?试想一下,程序要是复杂点或是有多个界面采用多线程来显示界面元素,那么采用前者,我们就算知道了异常的详细信息,但可能还是很难找到究竟是哪里出了问题。而通过MainUI来显示,情况就要好很多了,尤其是还设计到其他东西的时候(如:多语言环境)。当然,这个例子只是很小的一个方面。下面就来看怎么来实现:

  1. usingSystem;  
  2. usingSystem.Drawing;  
  3. usingSystem.Collections;  
  4. usingSystem.ComponentModel;  
  5. usingSystem.Windows.Forms;  
  6. usingSystem.Data;  
  7. usingSystem.Threading;  
  8.  
  9. namespaceThreadApp  
  10. {  
  11. publicclassfrmMain:System.Windows.Forms.Form  
  12. {  
  13. privateSystem.Windows.Forms.ButtonbtRun;  
  14. /**////  
  15. ///必需的设计器变量。  
  16. ///  
  17. privateSystem.ComponentModel.Containercomponents=null;  
  18.  
  19. publicdelegatevoidWorkerThreadExceptionHandlerDelegate(Exceptione);  
  20. voidWorkerThreadExceptionHandler(Exceptione)  
  21. {  
  22. this.Text="Disposed.";  
  23. MainUIThreadExceptionHandler(this,newSystem.Threading.ThreadExceptionEventArgs(e));  
  24. }  
  25.  
  26. publicfrmMain()  
  27. {  
  28. InitializeComponent();  
  29. }  
  30.  
  31. /**////  
  32. ///清理所有正在使用的资源。  
  33. ///  
  34. protectedoverridevoidDispose(booldisposing)  
  35. {  
  36. if(disposing)  
  37. {  
  38. if(components!=null)  
  39. {  
  40. components.Dispose();  
  41. }  
  42. }  
  43. base.Dispose(disposing);  
  44. }  
  45.  
  46. Windows窗体设计器生成的代码#regionWindows窗体设计器生成的代码  
  47. /**////  
  48. ///设计器支持所需的方法-不要使用代码编辑器修改  
  49. ///此方法的内容。  
  50. ///  
  51. privatevoidInitializeComponent()  
  52. {  
  53. this.btRun=newSystem.Windows.Forms.Button();  
  54. this.SuspendLayout();  
  55. //  
  56. //btRun  
  57. //  
  58. this.btRun.Location=newSystem.Drawing.Point(72,24);  
  59. this.btRun.Name="btRun";  
  60. this.btRun.TabIndex=0;  
  61. this.btRun.Text="Run";  
  62. this.btRun.Click+=newSystem.EventHandler(this.btRun_Click);  
  63. //  
  64. //frmMain  
  65. //  
  66. this.AutoScaleBaseSize=newSystem.Drawing.Size(6,14);  
  67. this.ClientSize=newSystem.Drawing.Size(224,69);  
  68. this.Controls.Add(this.btRun);  
  69. this.Name="frmMain";  
  70. this.Text="ThreadApp";  
  71. this.ResumeLayout(false);  
  72.  
  73. }  
  74. #endregion  
  75.  
  76. /**////  
  77. ///应用程序的主入口点。  
  78. ///  
  79. [STAThread]  
  80. staticvoidMain()  
  81. {  
  82. Application.ThreadException+=newThreadExceptionEventHandler(MainUIThreadExceptionHandler);  
  83. Application.Run(newfrmMain());  
  84. }  
  85.  
  86. publicstaticvoidMainUIThreadExceptionHandler(Exceptione)  
  87. {  
  88. MainUIThreadExceptionHandler(null,newSystem.Threading.ThreadExceptionEventArgs(e));  
  89. }  
  90.  
  91. publicstaticvoidMainUIThreadExceptionHandler(objectsender,ThreadExceptionEventArgst)  
  92. {  
  93. MessageBox.Show(t.Exception.Message,"Exception",  
  94. MessageBoxButtons.OK,  
  95. MessageBoxIcon.Warning);  
  96. }  
  97.  
  98.  
  99. privatevoidThrowException()  
  100. {  
  101. thrownewNotImplementedException();  
  102. }  
  103.  
  104. privatevoidRun()  
  105. {  
  106. try 
  107. {  
  108. this.Text="Waiting";//[错误]这里在2.0里是编译不通过的。因为它已经违背了我们的原则——不要跨线程操作(当前线程对界面线程的元素进行了操所)  
  109. Thread.Sleep(2000);  
  110. this.Text="ThrowException";  
  111. ThrowException();  
  112. this.Text="Finished";//[错误](同上)  
  113. }  
  114. catch(Exceptione)  
  115. {  
  116.  
  117. //如果涉及到多线程的互操作时,  
  118. //可以运用BeginInvoke方法来实现多线程间的互访问。  
  119. this.BeginInvoke(  
  120. newWorkerThreadExceptionHandlerDelegate(  
  121. WorkerThreadExceptionHandler),  
  122. newobject[]{e});}  
  123. }  
  124.  
  125. privatevoidbtRun_Click(objectsender,System.EventArgse)  
  126. {  
  127. ThreadStartts=newThreadStart(Run);  
  128. Threadt=newThread(ts);  
  129. t.Start();  
  130.  
  131. //thrownewNotSupportedException();  
  132. }  
  133. }  

【编辑推荐】

  1. 强类型和Actor:ActorLite的演示
  2. C#的Tag Message回顾:繁琐而危险
  3. Erlang的Actor回顾:将消息转化为逻辑执行
  4. Actor模型的本质:究竟是要解决什么问题
  5. 顺畅的使用C# Actor:另一个解决方案
责任编辑:彭凡 来源: cnblogs
相关推荐

2021-06-17 06:52:37

C#自定义异常

2009-08-04 13:53:58

C#委托类C#事件

2009-08-04 09:56:46

C#事件处理自定义事件

2009-08-03 16:37:49

C#异常类

2009-08-04 08:58:01

C#自定义特性

2010-12-24 15:38:53

C#单例模式

2009-08-03 13:34:06

自定义C#控件

2009-08-28 17:45:19

C#自定义数据

2009-08-03 13:39:46

C#自定义用户控件

2009-09-03 15:46:57

C#自定义事件

2009-08-12 14:53:50

C#类型转换函数

2009-08-04 12:40:34

c#自定义事件

2009-08-05 17:03:37

C#自定义控件

2009-08-04 12:56:51

C#自定义事件

2011-12-16 14:23:51

Java

2009-08-17 17:24:02

C#自定义消息框

2021-03-29 00:02:10

C#Attribute元素

2009-08-04 13:07:46

C#自定义快捷键

2009-08-04 09:09:51

C#反射

2009-08-04 13:31:35

C#自定义事件
点赞
收藏

51CTO技术栈公众号