【问题标题】:Sharing scope across awaits跨等待共享范围
【发布时间】:2014-04-17 07:32:21
【问题描述】:

我有一个UserScope 类,其功能类似于TransactionScope,即,它将当前状态存储在本地线程中。这当然不适用于对await 的调用,在.NET 4.5.1 中添加TransactionScopeAsyncFlowOption 之前TransactionScope 也没有。

我可以使用什么替代线程本地,以便UserScope 可以在单线程和多线程场景中同样使用? (如果我安装了 4.5.1,我会反编译以查看 TransactionScope 是如何做到的。)这是我所拥有的简化版本:

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() {
        ///...
    }
}

这是一个我希望工作的测试:

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

【问题讨论】:

标签: c# multithreading task-parallel-library async-await


【解决方案1】:

在 .NET 4.5 完整框架中,您可以为此使用逻辑调用上下文:

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

但是,您应该只将不可变数据存储在逻辑调用上下文中。我有more details on my blog。我一直想把它打包到一个 AsyncLocal<T> 库中,但还没有(还)找到时间。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-01-12
    • 2022-08-19
    • 1970-01-01
    • 1970-01-01
    • 2011-11-11
    • 2017-11-08
    • 1970-01-01
    • 2021-02-17
    相关资源
    最近更新 更多