zoukankan      html  css  js  c++  java
  • C# 线程手册 第六章 线程调试与跟踪 跟踪开关

      当你的程序接近部署阶段时,你可能想从代码中去掉所有的跟踪和调试消息。然而,你不得不从代码中一条一条地寻找调试指令并将其去掉。对于这种情况你可以在程序编译期间使用编译标志处理。从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 的例子…


    作者:DanielWise
    出处:http://www.cnblogs.com/danielWise/
    本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,否则保留追究法律责任的权利。

  • 相关阅读:
    对Spring 框架 AOP(面向切面)的理解
    页面自动刷新
    页面通过ajax传值到后台,后台返回值展示在页面输入框
    java中怎么跳出两层for循环
    人的三种思维角度
    我理解的战争(程序员是需要有立场的)
    我所理解的JavaScript中的prototype与__proto__、constructor
    一个"失速"项目的总结
    TDD学习笔记
    Java SQL动态生成库
  • 原文地址:https://www.cnblogs.com/danielWise/p/2470562.html
Copyright © 2011-2022 走看看