2013年9月17日 星期二

[轉貼] System.Diagnostics命名空間裡的Debug類別和Trace類別的用途

出處:http://www.cnblogs.com/jonescheng/archive/2008/04/07/1140768.html

System.Diagnostics命名空間裡的Debug類和Trace類的用途

摘要
在 .NET 類庫中有一個 System.Diagnostics 命名空間,該命名空間提供了一些與系統進程、事件日誌、和性能計數器進行交互的類庫。當中包括了兩個對開發人員而言十分有用的類——Debug類和Trace類。本文介紹了這兩個類的一些基本用途,旨在提高廣大開發人員的開發效率。

目錄
  • 使用Debug類來幫助調試
  • Debug類和Trace類的區別
  • 使用Trace類來做程序日誌
  • 小結
  • 參考資料

使用Debug類來幫助調試
調試程序對每個程序員來說是家常便飯。可是我們會經常遇到一些情況讓我們頭疼,例如:
  • 當我們在開發一個界面控件的時候,簡單的設斷點會增加Paint事件的響應次數,而造成的環境參數改變。
  • 斷點設多了,程序常常停在正常運行的地方;這樣一來,調試一個錯誤要花費大量時間去尋找錯誤。
這時,我們就需要利用System.Diagnostics.Debug類來幫助我們調試。我們可以通過調用Debug.WriteLine(String message)函數,將我們所關心的信息打印在Visual Studio IDE的Output窗口中。也可以利用Debug.Assert(bool condition)來讓程序停在錯誤的地方,並且顯示Call stack。
Debug類中所有函數的調用都不會在Release版本裡有效。也就是說,我們通過這種方法所加的代碼可以僅用於調試;在發佈的時候無需刪任何代碼,就可以給用戶一個沒有調試指令的程序了。
下面的這個例子演示了這兩個函數來幫助調試的方法:
1、 新建一個Visual Studio C# Project,採用默認的項目名。
2、 往Form1上拖一個label,並採用其缺省ID。
3、 在Form1.cs中的Form1類中添加下面的函數代碼:
private int time=0;
protected override void OnPaint(PaintEventArgs e)
{
time++;
this.label1.Text="OnPain called "+time.ToString()+" Times.";
}
protected override void OnResize(EventArgs e)
{
System.Diagnostics.Debug.Assert(this.Width>200,"Width should be larger than 200.");
System.Diagnostics.Debug.WriteLine(Size.ToString());
}
4、 編譯並運行項目的Debug版本。
5、 切換Visual Studio .NET IDE到Output窗口。
6、 切換到剛才的程序,改變主窗口的大小,您可以在IDE中看到Form1窗口的實時大小,並在Form1上看到OnPaint被調用的次數。當窗口的寬度小於等於200個像素的時候,系統會彈出一個Assertion Fail的對話框。裡面顯示了當前程序的Call Stack。如果您在OnPaint中設置了斷點,想要調試程序的話,那麼您會進入一個死循環,直到您停止調試。



Debug類和Trace類的區別
您一定發現了在System.Diagnostics命名空間中還有一個名為Trace的類。它的函數功能和Debug非常相似。為什麼要有這樣兩個功能類似的類呢?
原因是這樣的,Debug類裡所提供的函數僅在編譯時帶#Debug宏參數才奏效,一旦到了Release版本中,這些函數都會被忽略。也就是說Debug類的功能僅在程序員開發的時候能用。而Trace則不同,它能在Release版本的程序中也被運行,這樣程序員就可以在Release版本的程序中添加一些Debug類提供的功能了。

使用Trace類來做程序日誌
接下來的問題就是:我們程序員能利用Trace類的功能做些什麼呢?我們可以用它來做程序的日誌。
1、 打開剛剛的project。
2、 用下面的代碼覆蓋剛才第2步的代碼:
private void Calculate()
{
int a=1,b=1;
try
{
System.Random r = new Random();
while (true)
{
a=(int)(r.NextDouble()*10);
b=(int)(r.NextDouble()*10);
System.Diagnostics.Trace.WriteLine(System.DateTime.Now.ToString()+": "+
a.ToString()+"/"+b.ToString()+"="+(a/b).ToString());
}
}
catch (Exception ex)
{
System.Diagnostics.Trace.WriteLine(System.DateTime.Now.ToString()+": "+a.ToString()+
"/"+b.ToString()+"="+" ERROR: "+ex.Message);
MessageBox.Show(ex.Message);
}
}
3、 在構造函數Form1()的最後添加下面的代碼,將Trace的輸出重定向到app.log文件中:
System.Diagnostics.Trace.Listeners.Clear();
System.Diagnostics.Trace.AutoFlush=true;
System.Diagnostics.Trace.Listeners.Add(new System.Diagnostics.TextWriterTraceListener("app.log"));
4、 拖一個按鈕到該Form上,雙擊按鈕,在button1_Click函數中添加如下代碼:
Calculate();
Application.Exit();
5、 運行該程序的Release版本,點擊添加的按鈕,程序便開始執行一位隨機數除法。由於是隨機數,可能會出現出數為0的情況,這樣程序就會拋出Exception,這是程序會自動中止。
6、 在該程序所在的目錄裡您可以發現出現了一個新的文件app.log,裡面記錄了各個時刻的運算紀錄,並把Exception紀錄在日誌中。
 
 <system.diagnostics>
   <trace>
     <listeners>
       <add name="myListener" type="System.Diagnostics.TextWriterTraceListener,System" initializeData="c:\myListener.log" />
       <remove type="System.Diagnostics.DefaultTraceListener,System"/>
     </< span>listeners>
   </< span>trace>
</< span>system.diagnostics>
 
**************************************************************
自己整理的程式碼
using System;
using System.Diagnostics;
namespace Test_Console
{
    class Program
    {
        static void Main(string[] args)
        {
            string sProdName = "Widget";
            int iUnitQty = 100;
            double dUnitCost = 1.03;
 
            //輸出至 DOS CMD
            TextWriterTraceListener tr1 = new TextWriterTraceListener(System.Console.Out);
            Debug.Listeners.Add(tr1);
 
            //輸出至文字檔
            TextWriterTraceListener tr2 = new TextWriterTraceListener(System.IO.File.CreateText("Output.txt"));
            Debug.Listeners.Add(tr2);
 
            // Debug 模式才執行,Release 不執行
            Debug.WriteLine("Debug Information-Product Starting 開始 ");
            Debug.Indent();  //縮排
           
            Debug.WriteLine("The product name is " + sProdName);
            Debug.WriteLine("The product name is " + sProdName, "自訂標題");
           
            Debug.WriteLineIf(iUnitQty > 50, "This message WILL appear");
            Debug.WriteLineIf(iUnitQty < 50, "This message will NOT appear");
           
            Debug.Assert(dUnitCost > 1.0, "Message will NOT appear");
            Debug.Assert(dUnitCost < 1.0, "Message will appear since dUnitcost  < 1 is false");
 
            Debug.Unindent();  //取消縮排
            Debug.WriteLine("Debug Information-Product Ending 結束 ");
            Debug.WriteLine("");
            Debug.Flush();
 
            // Debug 或 Release 模式都會執行
            Trace.WriteLine("Debug Information-Product Starting 開始 ");
            Trace.Indent();  //縮排
 
            Trace.WriteLine("The product name is " + sProdName);
            Trace.WriteLine("The product name is " + sProdName, "自訂標題");
 
            Trace.WriteLineIf(iUnitQty > 50, "This message WILL appear");
            Trace.WriteLineIf(iUnitQty < 50, "This message will NOT appear");
 
            Trace.Assert(dUnitCost > 1.0, "Message will NOT appear");
            Trace.Assert(dUnitCost < 1.0, "Message will appear since dUnitcost  < 1 is false");
 
            Trace.Unindent();  //取消縮排
            Trace.WriteLine("Debug Information-Product Ending 結束 ");
            Trace.Flush();
 
            tr1.Close();
            tr2.Close();
        }
    }
}

沒有留言:

張貼留言