http://www.cnblogs.com/winnerlan/archive/2008/05/24/1206644.html
對.NET類來說,一般的異常類 System.Exception
派生於 System.Object。還有許多定義好的異常類(如:System.SystemException、System.ApplicationException等),他們又派生於
System.Exception 類。其中System.ApplicationException
類是第三方定義的異常類,如果我們要自訂異常類,那麼就應派生於它。
我們要站在異常一定可能會發生的角度來編寫例外處理常式,應對程式有可能發生的錯誤建立一個良好的異常處理策略。
在做異常處理的時候,最好能在應用程式所有的入口處(事件處理函數,主函數,線程入口)使用try-catch。但是不要在程式建構函式入口處添加try-catch,因為此處產生異常,它自己並沒有能力來處理,因為它還沒有構造完畢,只能再向外層拋出異常。
但我們也不能盲目使用異常。而且使用異常,可能會在一定程度上影響到程式的效能(C#中使用異常一般不影響效能)。
// 自訂異常類
public class MyException : ApplicationException
{
public MyException(string message) : base(message)
{
}
public MyException(string message,Exception innerException)
: base(message,innerException)
{
}
}
全域異常處理、多線程中的異常處理
將全域異常處理函數的委託加入到 Application.ThreadException
中,實現全域異常處理,但它只能處理主線程中未捕獲的異常。在多線程異常處理時,背景工作執行緒/輔線程中產生異常,可以把它轉給主線程來完成異常處理。如果線程之間不通知,是無法直接捕捉異常的。若沒有去處理背景工作執行緒/輔線程中產生的異常,該異常將會“消失”掉。
為什麼要把異常處理都交給主線程去做呢?舉個例子:在WinForm裡我們使用多線程來處理介面元素,一旦有異常發生就將異常訊息顯示出來。那麼,是直接在異常發生後就MessageBox,還是將訊息交給MainUI來統一顯示?試想一下,程式要是複雜點或是有多個介面採用多線程來顯示介面元素,那麼採用前者,我們就算知道了異常的詳細資料,但可能還是很難找到究竟是哪裡出了問題。而通過MainUI來顯示,情況就要好很多了,尤其是還設計到其他東西的時候(如:多語言環境)。當然,這個例子只是很小的一個方面。下面就來看怎麼來實現:
using System;
using System.Drawing;
using System.Collections;
using System.ComponentModel;
using System.Windows.Forms;
using System.Data;
using System.Threading;
namespace ThreadApp
{
public class frmMain : System.Windows.Forms.Form
{
private System.Windows.Forms.Button btRun;
///
/// 必需的設計器變數。
///
private System.ComponentModel.Container components = null;
public delegate void WorkerThreadExceptionHandlerDelegate(Exception e);
void WorkerThreadExceptionHandler(Exception e)
{
this.Text = "Disposed.";
MainUIThreadExceptionHandler(this, new System.Threading.ThreadExceptionEventArgs(e));
}
public frmMain()
{
InitializeComponent();
}
///
/// 清理所有正在使用的資源。
///
protected override void Dispose( bool disposing )
{
if( disposing )
{
if (components != null)
{
components.Dispose();
}
}
base.Dispose( disposing );
}
Windows 表單設計器產生的程式碼
///
/// 應用程式的主進入點。
///
[STAThread]
static void Main()
{
Application.ThreadException += new ThreadExceptionEventHandler(MainUIThreadExceptionHandler);
Application.Run(new frmMain());
}
public static void MainUIThreadExceptionHandler(Exception e)
{
MainUIThreadExceptionHandler(null, new System.Threading.ThreadExceptionEventArgs(e));
}
public static void MainUIThreadExceptionHandler(object sender, ThreadExceptionEventArgs t)
{
MessageBox.Show(t.Exception.Message,"Exception",
MessageBoxButtons.OK,
MessageBoxIcon.Warning);
}
private void ThrowException()
{
throw new NotImplementedException();
}
private void Run()
{
try
{
this.Text = "Waiting"; //[錯誤]這裡在2.0裡是編譯不通過的。因為它已經違背了我們的原則——不要跨線程操作(當前線程對介面線程的元素進行了操所)
Thread.Sleep(2000);
this.Text = "Throw Exception";
ThrowException();
this.Text = "Finished"; //[錯誤](同上)
}
catch(Exception e)
{
// 如果涉及到多線程的互操作時,
// 可以運用BeginInvoke方法來實現多線程間的互訪問。
this.BeginInvoke(
new WorkerThreadExceptionHandlerDelegate(
WorkerThreadExceptionHandler),
new object[]{e}); }
}
private void btRun_Click(object sender, System.EventArgs e)
{
ThreadStart ts = new ThreadStart(Run);
Thread t = new Thread(ts);
t.Start();
//throw new NotSupportedException();
}
}
}