2014-03-12 37 views
5

我有一個UserScope類,其功能類似於TransactionScope,即它將當前狀態存儲在本地線程中。這當然不適用於await的調用,並且TransactionScope也不工作,直到在.NET 4.5.1中添加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(); 
} 
+2

您不必再安裝.NET 4.5.1來查看它的源代碼。輸入[「.NET Reference Source的新外觀」](http://blogs.msdn.com/b/dotnet/archive/2014/02/24/a-new-look-for-net-reference-source。 ASPX)。特別是,['TransactionScope'](http://referencesource.microsoft.com/#System.Transactions/NetFx20/System.Transactions/System/Transactions/TransactionScope.cs#988b00261b7ce735)。我*真的*喜歡它,做得好,微軟:) – Noseratio

+1

@Noseratio:太棒了。我會檢查出來的。謝謝。 – Daniel

回答

6

在.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>庫中,但還沒有找到時間。

+0

非常好!謝謝。 – Daniel