共享范围等待

时间:2014-03-12 21:06:44

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

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

我可以使用什么替代线程本地,以便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();
}

1 个答案:

答案 0 :(得分:7)

在.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>库中,但还没有找到时间。