場景
在WEB系統開發中,我們經常面對這樣的需求:如何在一個請求中共享數據或對象實例?之前我都會用HttpContext.Current.Items。然而有一天我發現了兩個事實:一、每個請求都是在一個線程中執行的;二、[ThreadStatic]可以標注某個靜態字段為每個線程提供獨立的存儲。面對這兩個發現,我得出了這個結論:可以用[ThreadStatic]替換HttpContext.Current.Items。
問題
可以用[ThreadStatic]替換HttpContext.Current.Items嗎?
實驗
實驗素材
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Web; 5 using System.Web.UI; 6 using System.Web.UI.WebControls; 7 8 using System.Threading; 9 using System.IO; 10 11 namespace WebThreadStaticStudy 12 { 13 public partial class Test : System.Web.UI.Page 14 { 15 [ThreadStatic] 16 private static DateTime? Now; 17 private static int _Times = 1; 18 19 protected void Page_Load(object sender, EventArgs e) 20 { 21 if (Now == null) 22 { 23 Now = DateTime.Now; 24 } 25 26 if (HttpContext.Current.Items["Now"] == null) 27 { 28 HttpContext.Current.Items["Now"] = DateTime.Now; 29 } 30 31 string content=string.Format("第{0}次,線程:{1},ThreadStatic時間:{2},HttpContext.Current.Items時間:{3}。\r\n" 32 , _Times++ 33 , Thread.CurrentThread.ManagedThreadId 34 , Now 35 , HttpContext.Current.Items["Now"]); 36 37 this.Response.Write(content); 38 39 File.AppendAllText(@"F:\學習項目\規律化學習\WebThreadStaticStudy\WebThreadStaticStudy\Log.txt", content); 40 } 41 } 42 }
實驗結果
1 第1次,線程:8,ThreadStatic時間:2013/5/3 11:22:06,HttpContext.Current.Items時間:2013/5/3 11:22:06。 2 第2次,線程:10,ThreadStatic時間:2013/5/3 11:22:08,HttpContext.Current.Items時間:2013/5/3 11:22:08。 3 第3次,線程:8,ThreadStatic時間:2013/5/3 11:22:06,HttpContext.Current.Items時間:2013/5/3 11:22:08。 4 第4次,線程:10,ThreadStatic時間:2013/5/3 11:22:08,HttpContext.Current.Items時間:2013/5/3 11:22:09。 5 第5次,線程:11,ThreadStatic時間:2013/5/3 11:22:10,HttpContext.Current.Items時間:2013/5/3 11:22:10。 6 第6次,線程:10,ThreadStatic時間:2013/5/3 11:22:08,HttpContext.Current.Items時間:2013/5/3 11:22:10。 7 第7次,線程:8,ThreadStatic時間:2013/5/3 11:22:06,HttpContext.Current.Items時間:2013/5/3 11:22:10。 8 第8次,線程:11,ThreadStatic時間:2013/5/3 11:22:10,HttpContext.Current.Items時間:2013/5/3 11:22:11。 9 第9次,線程:8,ThreadStatic時間:2013/5/3 11:22:06,HttpContext.Current.Items時間:2013/5/3 11:22:12。 10 第10次,線程:11,ThreadStatic時間:2013/5/3 11:22:10,HttpContext.Current.Items時間:2013/5/3 11:22:12。
結論
不可以用[ThreadStatic]替換HttpContext.Current.Items。
原因分析
WEB服務器用線程池執行每個請求,多個不同時段執行的請求還是會共享同一個線程。
張占嶺 :線程池中的線程是可以被重用的,當你的請求結束后,當前線程結束,這時,其它客戶端可能用你上次的線程!