Sharing scope across awaits

 ̄綄美尐妖づ 提交于 2019-12-21 14:08:12

问题


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();
}

回答1:


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.



来源:https://stackoverflow.com/questions/22363830/sharing-scope-across-awaits

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!