Tha*_*niX 9 .net c# multithreading asynchronous task-parallel-library
我试图找到一种方法来跟踪异步任务执行流程的方式,以便在任务中很容易理解,启动它的原始流程是什么.我需要它主要用于记录,调试和保留特定执行流的一种堆栈跟踪.
例如:如果我的服务器具有来自多个IP的许多客户端,并且服务器需要为涉及许多异步操作的每个客户端执行工作流,则每个执行流程涉及许多不同的任务; 记录这样的流程是困难的,特别是在使用async/await机制时.
我还没有找到一种方法来包装任务,对于每个执行的任务,我会在记录时知道初始流程描述.例如,如果我为具有描述的操作启动新的任务流程 - "照顾10.0.3.4客户端",我希望能够在从该流程创建的任何任务中为此流程中的每个日志项添加此描述.
仅使用线程时,它很容易,因为您有线程静态变量.任务是不可能的......我甚至试图创建我自己的任务调度程序,它将包装任何使用它的任务(即使在使用async/await方法时)但由于任务调度程序库有时会使用新线程(尽管存在没有任何使用新线程的隐式请求) - 该方法TryExecuteTaskInline有时可以在新线程中运行.
任何想法或建议我如何实现这一目标?
i3a*_*non 13
您可以使用Trace.CorrelationManager.ActivityId存储逻辑操作ID,甚至更好地存储ImmutableStack逻辑操作ID.它存储在CallContext并通过async方法调用复制:
public static class LogicalFlow
{
private static readonly string _name = typeof (LogicalFlow).Name;
private static ImmutableStack<Guid> LogicalStack
{
get
{
return CallContext.LogicalGetData(_name) as ImmutableStack<Guid> ?? ImmutableStack.Create<Guid>();
}
set
{
CallContext.LogicalSetData(_name, value);
}
}
public static Guid CurrentId
{
get
{
var logicalStack = LogicalStack;
return logicalStack.IsEmpty ? Guid.Empty : logicalStack.Peek();
}
}
}
Run Code Online (Sandbox Code Playgroud)
你可以使用它作为一个,IDisposable所以你可以利用一个using范围,以确保Pop每个人都有Push:
private static readonly Popper _popper = new Popper();
public static IDisposable StartScope()
{
LogicalStack = LogicalStack.Push(Guid.NewGuid());
return _popper;
}
private sealed class Popper : IDisposable
{
public void Dispose()
{
LogicalStack = LogicalStack.Pop();
}
}
Run Code Online (Sandbox Code Playgroud)
用法:
using (LogicalFlow.StartScope())
{
Console.WriteLine(LogicalFlow.CurrentId);
await DoSomethingAsync();
Console.WriteLine(LogicalFlow.CurrentId);
}
Run Code Online (Sandbox Code Playgroud)
这个答案以前依靠Trace.CorrelationManager.LogicalOperationStack但是是LogicalOperationStack在.NET 4.5异步不兼容
| 归档时间: |
|
| 查看次数: |
1123 次 |
| 最近记录: |