gpt4 book ai didi

c# - 在异步调用中保留线程的上下文

转载 作者:太空宇宙 更新时间:2023-11-03 21:22:04 25 4
gpt4 key购买 nike

我试图通过将我的日志消息分组在一起来理清我的日志。理想情况下,我会向每条消息附加一些标识符,表明它是完成某项工作的一组命令的一部分。

如果这是一个单线程应用程序,线程的 ID 将是一个候选者。但是,此解决方案大量使用异步 Task,这妨碍了它的使用。是否有可能使类似下面的东西起作用,其中 Main() 的每次执行都将始终打印出相同的线程 ID?

static async void Main()
{
var t = Task.Run(async () => await MyAsyncMethod());
await t;
}

private static async Task MyAsyncMethod()
{
Debug.WriteLine("Log message: {0}", Thread.CurrentThread.ManagedThreadId);

await Task.Delay(1000);

Debug.WriteLine("Log message: {0}", Thread.CurrentThread.ManagedThreadId);

await Task.Delay(1000);

Debug.WriteLine("Log message: {0}", Thread.CurrentThread.ManagedThreadId);
}

最佳答案

IMO 的最佳方法是@SriramSakthivel 建议的方法:只需生成一个 ID 并将其传递。如果您有“消息”类型,则可以将其添加到该类型。

但是,如果这会导致过多的代码更改,那么您可以隐式传递它。我有一个 blog post with the gory details ;一般的想法是将数据存储为逻辑调用上下文的一部分:

public static class MyContext
{
private static readonly string name = Guid.NewGuid().ToString("N");

private sealed class Wrapper : MarshalByRefObject
{
public Guid Value { get; set; }
}

public static Guid CurrentContext
{
get
{
var ret = CallContext.LogicalGetData(name) as Wrapper;
return ret == null ? Guid.Empty : ret.Value;
}

set
{
CallContext.LogicalSetData(name, new Wrapper { Value = value });
}
}
}

然后您可以在您的代码中使用它:

private static async Task MyAsyncMethod()
{
MyContext.CurrentContext = Guid.NewGuid();

Debug.WriteLine("Log message: {0}", MyContext.CurrentContext);

await Task.Delay(1000);

Debug.WriteLine("Log message: {0}", MyContext.CurrentContext);

await Task.Delay(1000);

Debug.WriteLine("Log message: {0}", MyContext.CurrentContext);
}

请注意,此方法做出了两个关键假设:

  1. 您的代码在 .NET 4.5 或更新版本上运行。
  2. 存储的数据是不可变的(在这种情况下是正确的,因为 Guid 是不可变的)。

看起来像这样will be builtin在 .NET 4.6 中。

关于c# - 在异步调用中保留线程的上下文,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30038308/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com