代码改变世界

C# 线程手册 第六章 线程调试与跟踪 使用不同的监听器程序

2012-04-24 22:26  DanielWise  阅读(3653)  评论(1编辑  收藏  举报

  在这部分,我们将了解如何改变默认的监听器程序。Trace 类和Debug类暴露了监听器集合(一系列监听程序集合)。如果不添加任何新的监听类,DefaultTraceListener 将指向由Visual Studio.NET 提供的调试输出窗口。然而,.NET Framework 提供另外可以用作监听程序的两个类:

2012-4-24 21-22-30

  如果你需要跟踪一个不在Visual Studio 中执行的多线程应用程序的行为,那么你需要将默认监听器改成以上列表中的某一个。通常情况下,调试输出窗口仅在调试过程中可用。使用这两个类,你可以选择将跟踪消息写入Windows 事件日志中或者一个文本文件中。一般来说,如果你知道你的程序运行在一个有事件日志的操作系统中的话,那么使用EventLogTraceListener 类将是最好的选择。原因如下:

  1. 事件日志由操作系统管理;

  2. 事件日志允许管理员确定日志的安全设置;

  3. 事件日志需要使用事件日志查看器读取。这比用Notepad 读取的文本文件在阅读效果上要好得多(随着科技进步,也不尽然)。

改变默认的监听器程序很简单,我们来看一个例子,TraceEventLog.cs:

static void Main(string[] args)
{
    //Create a trace listener for the event log.
    EventLogTraceListener eltl = new EventLogTraceListener("TraceLog");

    //Add the event log trace listener to the collection.
    Trace.Listeners.Add(eltl);

    //Write output to the event log.
    Trace.WriteLine("Entered in Main()");
}

  首先,我们需要创建一个新的监听器对象。在上面的例子中,为了将Windows 事件日志作为监听器程序我们创建了一个新的EventLogTraceListener 对象。这个类的构造函数接收一个字符串作为参数,用于设置写入记录的日志源名称。构造函数将会实例化一个新的EventLog 对象并自动地使用输入参数值设置EventLog 类的Source 属性。

  下一步是使用Add() 方法向集合中添加一个新的监听器对象并向监听器对象提供其引用。最后,我们可以开始写入跟踪消息,这些消息将被中转给监听程序。

  使用事件日志查看器(开始菜单->运行->输入 eventvwr)打开Windows 事务日志, 你将在应用程序部分看到一条新的日志:

2012-4-24 21-39-50

  你可以双击应用程序日志中对应的记录并检查其中的内容:

2012-4-24 21-40-30

  上面的代码在监听器集合中添加了一个新的监听器,所以你将同时在调试输出窗口和Windows 事件日志中看到消息。如果你想移除默认的监听器而只使用事件日志的话,你需要使用RemoveAt() 方法,如下所示:

static void Main(string[] args)
{
    //Create a trace listener for the event log.
    EventLogTraceListener eltl = new EventLogTraceListener("TraceLog");

    //Remove the default listener
    Trace.Listeners.RemoveAt(0);

    //Write output to the event log.
    Trace.WriteLine("Entered in Main()");
}

TextWriterTraceListener 类

我们将要通过检查TextWriterTraceListener类来进一步了解监听器。当你需要将跟踪消息直接写到一个文本文件中或者一个控制台应用程序中的话使用它会很有用。事实上,在创建一个TextWriterTraceListener对象过程中,你可以确定使用一个TextWriter 对象或者一个Stream 对象。使用一个Stream 对象允许你设定更多关于如何处理文件流的选项。下面的代码片段,TraceConsole.cs, 显示了如何在控制台中跟踪消息:

static void Main(string[] args)
{
    //Remove the default listener.
    Trace.Listeners.RemoveAt(0);

    //Add a console listener
    Trace.Listeners.Add(new TextWriterTraceListener(Console.Out));

    //Write a trace message.
    Trace.WriteLine("Entered in Main()");

}

由于在类的构造函数中设定Console.Out 流作为监听器,所以我们的控制台程序将显示跟踪消息:

2012-4-24 21-51-43

最后,让我们看看如何添加文本日志文件作为监听器。我们需要添加一个新的TextWriterTraceListener 对象,在构造函数中使用一个FileStream 对象。当程序结束以后,你需要使用Trace 类提供的静态Close() 方法来显式地关闭日志同时写入所有消息。在下面的代码中,Debugging.s, 使用主次线程来跟踪消息:

static void WritingThread()
{
    //Trace an info message
    Trace.WriteLine(DateTime.Now + " - Entered WritingThread()");

    Thread.Sleep(1000);

    //Trace an info message
    Trace.WriteLine(DateTime.Now + " - Slept for 1 second...");
}

线程使用WritingThread() 方法来睡眠一秒然后写一些跟踪消息。

这里我们创建了一个新的FileStream 对象,如果文件存在则打开否则新建一个。然后,我们在Add()方法中创建一个TextWriterTraceListener 类的新的实例并将其添加到监听器集合中:

FileStream fs = new FileStream(@"C:\Debugging.log", FileMode.OpenOrCreate);
Trace.Listeners.Add(new TextWriterTraceListener(fs));

启动线程以后,代码等待用户输入回车键然后关闭监听器程序并将所有跟踪信息写入到日志文件中:

Trace.WriteLine(DateTime.Now + "- Entered Main()");

Thread t = new Thread(new ThreadStart(WritingThread));
t.Start();

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

代码的输出结果如下:

2012/4/24 22:22:35- Entered Main()
2012/4/24 22:22:35- Entered WritingThread()
2012/4/24 22:22:36- Slept for 1 second...

Trace 类提供了一个有用的属性IndentLevel 来缩进跟踪消息。例如,你可以在主次线程中使用不同的缩进级别写跟踪消息。在上面代码中添加如下一行代码,我们就可以轻松地实现这个功能:

private static void WritingThread()
{
    //Setting indent level
    Trace.IndentLevel = 2;
    Trace.WriteLine(DateTime.Now + "- Entered WritingThread()");
    Thread.Sleep(1000);
    Trace.WriteLine(DateTime.Now + "- Slept for 1 second...");
}

修改后的代码输出结果如下:

2012/4/24 22:22:35- Entered Main()
        2012/4/24 22:22:35- Entered WritingThread()
        2012/4/24 22:22:36- Slept for 1 second...

你也可以使用Indent() 和 Unindent() 方法来对应的增加或者减少缩进等级。

 

下一篇介绍跟踪开关…