在MSDN中,我发现了一篇关于如何为特定操作分配一些跟踪的文章.在Microsoft服务跟踪查看器中检查跟踪日志时,这很方便,因为您可以单击某个活动以查看该特定操作的进展情况.
以下是本文中的代码示例,如何为操作分配一些跟踪事件:
Guid traceID = Guid.NewGuid();
ts.TraceTransfer(0, "transfer", traceID);
Trace.CorrelationManager.ActivityId = traceID; // Trace is static
ts.TraceEvent(TraceEventType.Start, 0, "Add request");
Run Code Online (Sandbox Code Playgroud)
问题是:CorrelationManager是静态的,因此影响整个应用程序.你在多线程应用程序中做什么?不幸的是,我发现无法完成多个并行活动.提前致谢!
跟踪是静态的.但是,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);
}
}
}
Run Code Online (Sandbox Code Playgroud)
如您所见,只有一个Trace"对象"(因为它是静态的)并且只有一个CorrelationManager(因为它是一个属性,一个真实的对象实例,在Trace对象上).通过CallContext对象实现上下文数据(ActivityId和LogicalOperationStack)的每线程实例化.
通过CallContext.LogicalSetData存储的数据也"流"到下游线程.因此,如果在线程的开头设置ActivityId并且该线程随后生成线程(可能产生其他线程),则所有这些下游线程将具有相同的ActivityId.
您可以在此处查看Trace和CorrelationManager的源代码(不确定.Net的版本来自哪个版本,但我怀疑它与Trace和CorrelationManager今天的工作方式非常接近: