在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是静态的,因此会影响整个应用程序。你在多线程应用程序中做什么? 不幸的是,我发现无法完成多个并行活动。 提前谢谢!
答案 0 :(得分:5)
跟踪是静态的。但是,CorrelationManager以线程本地存储的形式存储ActivityId和LogicalOperationStack。 CorrelationManager使用CallContext.LogicalSetData在CallContext中存储值。
这意味着每个线程都可以拥有自己的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今天的工作方式非常接近: