本文介绍了等待着对面共享范围的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个 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.

这篇关于等待着对面共享范围的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-16 17:41