Ger*_*ard 14 .net c# multithreading
如何ThreadStatic在TPL任务中使用?我的理解("使用C#进行Wrox Professional Parallel Programming",第74页)是一个Task可以在执行期间从一个线程切换到另一个线程.
我想做的事?
我想在静态类中维护一个会话ID,所以我不需要将这个id传递给我的所有方法.我的库有类似的方法login(id),logout(id)以及许多与此id相关的凭证进行操作的方法.但我不想将此id传递给每个方法.我可以确保在不同的线程中为不同的会话调用我的库.因此,将id保存login()在ThreadStatic变量中将起作用.
现在我想使用由我创建的TPL任务ThreadPool.我可以将我的会话ID传递给Task,但是如果我将这个id存储在ThreadStatic变量中,那么如果我的Task切换线程,它将无法生存.
TPL和.NET 4.5的异步流动ExecutionContext,这意味着你可以用CallContext.LogicalSetData(string, object)和CallContext.GetLogicalData(string)在大致相同的方式,你会使用ThreadStatic。但是,它确实会导致显着的性能损失。这已被暴露在.net 4.6和最多(包括.Net标准1.3及以上)用的AsyncLocal<>包装。
请参阅异步因果链跟踪、如何在 ExecutionContext 中包含自己的数据以及ExecutionContext 与 SynchronizationContext以获得更深入的了解。
使用示例:
class Program
{
static async void Main(string[] args)
{
Logger.Current = new Logger("Test Printer");
Logger.Current.Print("hello from main");
await Task.Run(() => Logger.Current.Print($"hello from thread {Thread.CurrentThread.ManagedThreadId}"));
await Task.Run(() => Logger.Current.Print($"hello from thread {Thread.CurrentThread.ManagedThreadId}"));
}
}
class Logger
{
private string LogName;
public Logger(string logName)
{
if (logName == null)
throw new InvalidOperationException();
this.LogName = logName;
}
public void Print(string text)
{
Console.WriteLine(LogName + ": " + text);
}
private static AsyncLocal<Logger> _logger = new AsyncLocal<Logger>();
public static Logger Current
{
get => _logger.Value;
set => _logger.Value = value;
}
}
}
Run Code Online (Sandbox Code Playgroud)
印刷:
测试打印机:来自主的你好 测试打印机:来自线程 11 的你好 测试打印机:来自线程 10 的你好
| 归档时间: |
|
| 查看次数: |
2094 次 |
| 最近记录: |