问题描述
我有一个 UserScope
类,它的功能类似于的TransactionScope
,也就是说,它存储在一个线程的当前状态本地。当然,这并不在调用工作等待
,并且也没有的TransactionScope
直到 TransactionScopeAsyncFlowOption
在.NET 4.5.1加入。
什么替代线程本地我可以使用,使 UserScope
可在单线程和多线程的场景中使用相同的? (如果我已经安装了4.5.1我编译怎么看的TransactionScope
做的。)这是什么,我有一个简化版本:
类用户{
只读字符串名称; 公共用户(字符串名称){
this.name =名称;
} 公共字符串名称{
{返回this.name; }
}
}类UserScope:IDisposable的{
只读用户的用户; [ThreadStatic]
静态UserScope currentScope; 公共UserScope(用户用户){
this.user =用户;
currentScope =这一点;
} 公共静态用户用户{
{返回currentScope!= NULL? currentScope.user:空; }
} 公共无效的Dispose(){
/// ...
}
}
这是一个测试,我期望的工作:
静态异步任务测试(){
VAR用户=新用户(线程打火石);
使用(新UserScope(用户)){
等待Task.Run(代表{
Console.WriteLine(与NRE崩溃...);
Console.WriteLine(当前用户:{0},UserScope.User.Name);
});
}
}静态无效的主要(字串[] args){
。测试()等待();
到Console.ReadLine();
}
在.NET 4.5完整的框架,你可以使用逻辑调用上下文这样的:
静态异步任务测试()
{
CallContext.LogicalSetData(姓名,线程打火石);
等待Task.Run(代表
{
与NRE //Console.WriteLine(\"Crashing ......);
Console.WriteLine(当前用户:{0},CallContext.LogicalGetData(姓名));
});
}静态无效的主要(字串[] args)
{
。测试()等待();
到Console.ReadLine();
}
然而,你应该只存储在逻辑调用上下文不可变数据。我有我的博客 更多细节。我一直来包装这件事到 AsyncLocal< T>
库,但还没有(还)发现时间
I have a UserScope
class which functions similarly to TransactionScope
, i.e., it stores the current state in a thread local. This of course doesn't work across calls to await
, and neither did TransactionScope
until TransactionScopeAsyncFlowOption
was added in .NET 4.5.1.
What alternative to thread local can I use so that UserScope
can be used the same in single-threaded and multi-threaded scenarios? (If I had 4.5.1 installed I'd decompile to see how TransactionScope
does it.) This is a simplified version of what I have:
class User {
readonly string name;
public User(string name) {
this.name = name;
}
public string Name {
get { return this.name; }
}
}
class UserScope : IDisposable {
readonly User user;
[ThreadStatic]
static UserScope currentScope;
public UserScope(User user) {
this.user = user;
currentScope = this;
}
public static User User {
get { return currentScope != null ? currentScope.user : null; }
}
public void Dispose() {
///...
}
}
And this is a test I'd expect to work:
static async Task Test() {
var user = new User("Thread Flintstone");
using (new UserScope(user)) {
await Task.Run(delegate {
Console.WriteLine("Crashing with NRE...");
Console.WriteLine("The current user is: {0}", UserScope.User.Name);
});
}
}
static void Main(string[] args) {
Test().Wait();
Console.ReadLine();
}
In .NET 4.5 full framework, you can use the logical call context for this:
static async Task Test()
{
CallContext.LogicalSetData("Name", "Thread Flintstone");
await Task.Run(delegate
{
//Console.WriteLine("Crashing with NRE...");
Console.WriteLine("The current user is: {0}", CallContext.LogicalGetData("Name"));
});
}
static void Main(string[] args)
{
Test().Wait();
Console.ReadLine();
}
However, you should only store immutable data in the logical call context. I have more details on my blog. I've been meaning to wrap this up into an AsyncLocal<T>
library, but haven't (yet) found the time.
这篇关于等待着对面共享范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!