代码改变世界

C# 线程手册 第六章 线程调试与跟踪 跟踪开关

2012-04-25 21:41  DanielWise  阅读(2684)  评论(4编辑  收藏  举报

  当你的程序接近部署阶段时,你可能想从代码中去掉所有的跟踪和调试消息。然而,你不得不从代码中一条一条地寻找调试指令并将其去掉。对于这种情况你可以在程序编译期间使用编译标志处理。从Visual Studio.NET IDE, 你可以在解决方案管理窗口右键工程名->从菜单页选择属性。如下图对话框显示:

2012-4-25 20-06-19

  你只需要简单地将定义调试常量和跟踪常量选项勾掉,重新编译解决方案,所有的跟踪和调试代码都将会被从应用程序中被去掉。

  为了去掉跟踪功能,你可以使用csc.exe 命令行编译器。在编译时使用/d:TRACE=FALSE /d:DEBUG=FALSE 开关。

  对跟踪代码添加开关功能允许我们在运行时激活/反激活跟踪消息。通过简单地在我们程序的配置文件中定义一个值,你就可以激活跟踪功能而不用重新编译代码。通常情况下,为了维持跟踪信息你需要将其集成到应用程序中,结果就是程序变得越来越大、越来越慢,即便跟踪开关已经被关闭。

  BooleanSwitch 和 TraceSwitch 类是.NET Framework 提供来是实现这些开关的。让我们先来看看BooleanSwitch 类。

BooleanSwitch 类

  在跟踪代码中使用这个类,你可以通过简单地改一下配置文件来激活/反激活消息。WriteLineIf() 和 WriteIf() 方法根据BooleanSwitch 类的Enabled 属性决定是否写消息。为了在你的程序中添加开关你需要按以下步骤执行:

  1. 手动添加一个配置文件或者通过在项目菜单添加一个新文件来添加App.config 文件。

  2. 打开配置文件添加如下信息。0 表示禁用跟踪功能,1 表示激活跟踪功能。

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <system.diagnostics>
    <switches>
      <add name="MySwitch" value ="1"/>
    </switches>
  </system.diagnostics>
</configuration>

  3. 在代码中创建一个新的BooleanSwitch 对象并设置其名字与配置文件中的一样。在下面的代码中我们定义一个全局BooleanSwitch对象:

static BooleanSwitch bs;

static void Main(string[] args)
{
    //Create a Boolean switch called MySwitch
    bs = new BooleanSwitch("MySwitch", "Enable/Disable tracing functionalites");

    //Create a file listener
    FileStream fs = new FileStream(@"D:\Debugging.log", FileMode.OpenOrCreate);
    Trace.Listeners.Add(new TextWriterTraceListener(fs));

    //Write the line only when the switch is on
    Trace.WriteLineIf(bs.Enabled, DateTime.Now + "- Entered in Main()");

}

  在Main() 方法中我们创建了对象,并使用与配置文件中相同的名字对其初始化。WriteLineIf() 方法仅当配置文件中的Enabled 设置为1 时才写消息。

TraceSwitch 类

  这个类是BooleanSwitch 类的高级版本因为它允许我们选择是否反激活跟踪功能或者按照不同重要层次来显示信息。下表列出了不同等级:

2012-4-25 20-58-32

  所以,当发生了一个错误时,你可以改变应用程序配置文件,来设定只向监听程序写入你加到代码中的错误信息,这样可以仅关注这些信息。配置文件的设置与BooleanSwitch 例子相同。代码中的改变是我们需要从TraceSwitch 类来实例化一个对象。还有我们将在类中使用枚举来确定跟踪消息的层次。现在来看一个例子,TraceSwitchExample.cs:

static TraceSwitch ts;

[STAThread]
static void Main(string[] args)
{
    //Create a BooleTraceSwitchan switch called MySwitch
    ts = new TraceSwitch("MySwitch", "Four different trace levels");
    //Create a file listener
    FileStream fs = new FileStream(@"D:\Debugging.log", FileMode.OpenOrCreate);
    Trace.Listeners.Add(new TextWriterTraceListener(fs));

    //Write the line only when the switch is on
    Trace.WriteLineIf(ts.TraceInfo, DateTime.Now + "- Entered in Main()");;

    //Create a thread
    Thread t = new Thread(new ThreadStart(DBThread));
    t.Start();

    Console.ReadLine();
    Trace.Close();
}

  我们定义了一个全局TraceSwitch 对象然后通过配置文件中的名字生成一个新的实例。我们添加一个文本监听器到程序中。然后启动一个新线程来连接数据库获得Region 表中的所有信息。

  如果线程已经启动而且Open() 方法产生一个异常时将会产生一条错误消息:

private static void DBThread()
{
    Trace.WriteLineIf(ts.TraceInfo, DateTime.Now + "- Entered in 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;

    try
    {
        Trace.WriteLineIf(ts.TraceInfo, DateTime.Now + "- Execute SQL statement");
        //Open the connection to the database
        dbConn.Open();
        //Execute the SQL statement
        dr = dbComm.ExecuteReader(System.Data.CommandBehavior.CloseConnection);
        while (dr.Read())
        {
            //Reading records
            Trace.WriteLine(dr[0].ToString());
        }
    }
    catch (Exception ex)
    {
        //Log the error to the Trace application
        Trace.WriteLineIf(ts.TraceError, DateTime.Now + " An error occured in database access, details: " + ex.Message);
    }
    finally
    {
        if (!dr.IsClosed && dr != null)
        {
            dr.Close();
        }
    }
}

  当在配置文件中设定值为1时,TraceError 信息的输出结果如下:

2012/4/25 21:35:29 An error occured in database access, details: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。
未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: SQL 网络接口, error: 26 - 定位指定的服务器/实例时出错)

  当配置文件中设定值为3时,TraceInformation 信息的输出结果如下:

2012/4/25 21:37:10- Entered in Main()
2012/4/25 21:37:12- Entered in DBThread()
2012/4/25 21:37:12- Execute SQL statement
2012/4/25 21:37:27 An error occured in database access, details: 在与 SQL Server 建立连接时出现与网络相关的或特定于实例的错误。
未找到或无法访问服务器。请验证实例名称是否正确并且 SQL Server 已配置为允许远程连接。 (provider: SQL 网络接口, error: 26 - 定位指定的服务器/实例时出错)

Debug 类

  Debug 类提供与Trace 类同样的功能。当你改变Trace 类提供的监听器集合中的监听器程序时,你可以在Debug 类中做同样的事情。

  这两个类最大的不同在于应用的不同场景。Debug 类用于调试阶段添加信息。在部署我们的应用程序之前,你将创建一个发布版本同时自动去除所有调试信息。因此,你可以在程序运行阶段需要的时候添加Trace 类功能。

 

下一篇介绍一个DataImport 的例子…