我們下一個將要分析的代碼檢測技術是跟蹤。在一個多線程應用程序中,這個技術非常重要。當已經啟動了多個任務時,你可以跟蹤一個線程的行為和相互之間的各個線程之間的影響。我們稍后將看到在這種情況下使用調試器是不現實的。.NET Framework 提供了很多有用的類來幫助開發人員輕松地實現跟蹤功能。讓我們看一下.NET Framework 提供的System.Diagnostics 命名空間中的跟蹤類。
1. Trace: 這個類有很多向一個監聽器寫消息的靜態方法。默認情況下,VS.NET 中的調試輸出窗口將被用來作為監聽程序,由於使用了監聽器集合,所以你可以添加不同的監聽器,比如文本監聽器或者Windows事件日志監聽器。
2. Debug: 這個類的方法和Trace 類的一樣,都向一個監聽器應用程序中寫入信息。這兩個類在使用上最大的不同是,Trace 用於運行階段,Debug 用於開發階段。
3. BooleanSwitch: 這個類允許我們定義一個開關來打開/關閉跟蹤消息。
4. TraceSwitch: 這個類提供四個不同的跟蹤級別來幫助開發人員選擇發送不同級別的消息給監聽器。
Trace 類
在這部分,我們將分析Trace 類中使用最頻繁的幾個方法。這些方法由.NET Framework包裝好后提供給我們。Trace 類位於System.Diagnostics 命名空間中並提供很多靜態方法來發送消息給監聽程序。
下表列出來由Trace 類提供的一些靜態方法:
這些方法的默認行為取決於選擇的監聽器程序。例如,當使用默認監聽器的時候,Assert() 方法會顯示一個消息框。
默認監聽器程序
Trace 類提供一個允許我們添加一個新的監聽器程序的監聽器集合。當沒有向監聽器集合中添加新的監聽器對象時,Trace 類就會使用默認的監聽器程序:調試輸出窗體。這個窗體由Visual Studio.NET IDE 在調試過程中提供。讓我們來看一個簡單的例子,TraceExample:
/************************************* /* Copyright (c) 2012 Daniel Dong * * Author:Daniel Dong * Blog: www.cnblogs.com/danielWise * Email: guofoo@163.com * */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; namespace TraceExample { class Program { static void Main(string[] args) { Trace.WriteLine("Enter Main()"); for (int i = 0; i < 6; i++) { Trace.WriteLine(i); } Trace.WriteLine("Exiting from Main()"); } } }
這段代碼真的非常簡單;當進入和退出Main() 方法時它打出調試信息,在循環中累加變量值。在下一個截圖中,你可以看到Visual Studio.NET 輸出監聽器是如何顯示信息的:
Trace 類也提供了兩個有用的方法來斷言錯誤提示:Assert() 和 Fail(). 前者允許開發人員檢查作為參數傳入的條件是否滿足並在條件不滿足時向監聽器中寫入一條消息。后者會在每次發生失敗時向監聽器中寫入一條消息。當監聽器集合中沒有其他監聽器對象時,Assert() 方法顯示一個消息對話框來提供用戶斷言失敗。下面的代碼片段,TraceAssert.cs, 可以在SQL Server 服務被故意停止且引發一個連接錯誤的時候測試出來:
/************************************* /* Copyright (c) 2012 Daniel Dong * * Author:Daniel Dong * Blog: www.cnblogs.com/danielWise * Email: guofoo@163.com * */ using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Diagnostics; using System.Threading; using System.Data.SqlClient; namespace TraceExample { class Program { [STAThread] static void Main(string[] args) { //Create a thread Thread t = new Thread(new ThreadStart(DBThread)); //Start the thread t.Start(); } private static void DBThread() { //Create a connection object SqlConnection dbConn = new SqlConnection(@"Data Source=DANIELFORWARD\SQLEXPRESS;Initial Catalog=Northwind;Integrated Security=True"); //Create a command object to execute a SQL statement SqlCommand dbComm = new SqlCommand("SELECT * FROM Region", dbConn); SqlDataReader dr = null; Trace.WriteLine(DateTime.Now + "- Execute SQL statement"); try { //Open the connection to the database dbConn.Open(); //Assert that the connection opened Trace.Assert(dbConn.State == System.Data.ConnectionState.Open, "Error", "Connection failed..."); //Execute the SQL statement dr = dbComm.ExecuteReader(System.Data.CommandBehavior.CloseConnection); //Assert that the statement executed OK Trace.Assert(dr != null, "Error", "The SqlDataReader is null."); while (dr.Read()) { //Reading records Trace.WriteLine(dr[0].ToString()); } } catch (Exception ex) { //Log the error to the Trace application Trace.Fail("An error occured in database access, details: " + ex.Message); } finally { if (!dr.IsClosed && dr != null) { dr.Close(); } } } } }
在Main() 方法中,創建並啟動了一個新線程。新線程運行DBThread()中的代碼。代碼簡單地連接了下SQL Server 的Northwind數據庫,從Region表中收集所有數據。如果SQL Server 不可用,在執行代碼過程中會彈出下面的斷言失敗窗體。
引發異常斷言的代碼為:
Trace.Assert(dbConn.State == System.Data.ConnectionState.Open, "Error", "Connection failed...");
你可以看到,第一個參數檢查連接狀態是否打開。當連接沒有打開時它將被設置為false, 然后會顯示斷言失敗。你將會從本章的后續部分了解到也可以使用配置文件禁用消息跟蹤。那樣的話,你就可以在運行時決定是否顯示斷言消息。
下一篇介紹如何使用不同的監聽程序…



