使用并发线程跟踪操作

时间:2011-10-18 15:46:45

标签: .net tracing

在MSDN中,我找到了一个关于如何为特定操作分配一些跟踪的article。在Microsoft服务跟踪查看器中检查跟踪日志时,这很方便,因为您可以单击某个活动以查看该特定操作的进度。

以下是本文中的代码示例,如何为操作分配一些跟踪事件:

Guid traceID = Guid.NewGuid();
ts.TraceTransfer(0, "transfer", traceID);
Trace.CorrelationManager.ActivityId = traceID; // Trace is static
ts.TraceEvent(TraceEventType.Start, 0, "Add request");

问题是:CorrelationManager是静态的,因此会影响整个应用程序。你在多线程应用程序中做什么? 不幸的是,我发现无法完成多个并行活动。 提前谢谢!

1 个答案:

答案 0 :(得分:5)

跟踪是静态的。但是,CorrelationManager以线程本地存储的形式存储ActivityId和LogicalOperationStack。 CorrelationManager使用CallContext.LogicalSetDataCallContext中存储值。

这意味着每个线程都可以拥有自己的ActivityId和LogicalOperationStack。

在伪代码中,Trace.CorrelationManager和CorrelationManager.ActivityId的实现看起来像这样:

public static class Trace
{
  private static correlationManager = null;
  public CorrelationManager CorrelationManager
  {
    get
    {
      if (correlationManager == null) correlationManager = new CorrelationManager();
      return correlationManager;
    }
  }
}


public class CorrelationManager
{
  public Guid ActivityId
  {
    get
    {
      object id = CallContext.LogicalGetData("CorelationManager.ActivityId");
      if (id == null)
      {
        return Guid.Empty;
      }
      return (Guid) id;
    }
    set
    {
      CallContext.LogicalSetData("CorrelationManager.ActivityId", value);
    }
  }
}

正如您所看到的,只有一个Trace“对象”(因为它是静态的)并且只有一个CorrelationManager(因为它是一个属性,一个真实的对象实例,在Trace对象上)。上下文数据(ActivityId和LogicalOperationStack)的每线程实例化是通过CallContext对象实现的。

通过CallContext.LogicalSetData存储的数据也“流向”下游线程。因此,如果您在线程的开头设置ActivityId并且该线程随后生成线程(可能会产生其他线程),那么所有这些下游线程将具有相同的ActivityId。

你可以在这里看到Trace和CorrelationManager的源代码(不确定.Net的版本来自哪个版本,但我怀疑它与Trace和CorrelationManager今天的工作方式非常接近:

Trace

CorrelationManager