跟踪C#/。NET的任务流程 [英] Tracking c#/.NET tasks flow
问题描述
我试图找到一种方法来保持对异步任务执行流程轨道的方式,它会很容易理解有关的任务,那是什么引发它原来的流程。
I'm trying to find a way to keep a track on async tasks execution flow in a way that it would be easy to understand regarding task, what was the original flow that initiated it.
我需要它主要用于日志记录,调试和preserving一种堆栈跟踪的一个特定的执行流程。
I need it mostly for logging, debugging and preserving a sort of stack trace for a specific execution flow.
例如:如果我有服务器与许多客户来自多个IP地址和服务器需要 执行每个涉及这样涉及每次执行流程许多不同的任务很多异步操作的客户端工作流;记录这样的流动困难,特别是使用异步时/等待机制。
for example: if i have server with many clients from multiple IPs and the server need to execute a work flow for each client that involves many async actions thus involves many different tasks per execution flow; logging such a flow is difficult especially when using async/await mechanism.
我还没有想出一个办法来包装任务的方式,对被执行的每项任务我会知道最初的流程描述登录时,例如,如果我开始工作的一个新的流程与说明动作 - 以10.0.3.4客户关怀我希望能够加入这个说明每个日志项从这个流程中,从它创建的任何任务现身
I haven't figure out a way to wrap the tasks in a way that for each task that is executed i would know the initial flow description when logging, for example if i start a new flow of tasks for an action with description - "Taking care of 10.0.3.4 client" i want to be able to add this description for each log item coming out from this flow in any task that created from it.
在使用线程只是它的简单,因为你有螺纹静态变量。交任务了不可能的... 我甚至想创建自己的任务调度程序,将包装出一个使用它的任何任务(使用异步当即便/ await方法),但钻进了死胡同,因为任务调度的基础有时会使用新的线程(即使没有任何隐请求使用一个新的线程) - 方法TryExecuteTaskInline有时会在一个新的线程中运行
When using threads only its easy because you have thread static variables. with tasks its impossible... I even tried to create my own task scheduler that will wrap out any task that uses it (even when using async/await methods) but got into a dead end because the task scheduler base sometimes uses new thread (even though there wasn't any implicit request to use a new thread)- the method "TryExecuteTaskInline" can sometimes run in a new thread.
我怎么能做到这一点的任何想法或建议?
Any idea or suggestion of how can i achieve that?
推荐答案
您可以使用<一个href="http://msdn.microsoft.com/en-us/library/system.diagnostics.correlationmanager.activityid(v=vs.110).aspx"相对=nofollow> Trace.CorrelationManager.ActivityId
存储逻辑操作ID,甚至更好的存储的 ImmutableStack
逻辑运算IDS。它被保存在 CallContext中
并通过复制异步
方法调用:
You can use Trace.CorrelationManager.ActivityId
to store a logical operation id, or even better store an ImmutableStack
of logical operation ids. It is stored in the CallContext
and is copied through the async
method calls:
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();
}
}
}
您可以使用它作为一个的IDisposable
这样你就可以利用使用
的范围,以确保有一个流行
每按
:
You can use it as an IDisposable
so you can utilize a using
scope to make sure there's a Pop
to every 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();
}
}
用法:
using (LogicalFlow.StartScope())
{
Console.WriteLine(LogicalFlow.CurrentId);
await DoSomethingAsync();
Console.WriteLine(LogicalFlow.CurrentId);
}
这答案previously依赖于 Trace.CorrelationManager.LogicalOperationStack
但为 LogicalOperationStack
与异步不兼容的.Net 4.5
This answer previously relied on Trace.CorrelationManager.LogicalOperationStack
but Is LogicalOperationStack
incompatible with async in .Net 4.5
这篇关于跟踪C#/。NET的任务流程的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!