在頁面對象或者HttpContext對象中,都有一個名爲Session的屬性,在一次會話中,它們引用的都是同一個對象。javascript
public HttpSessionState Session { get; }
Session對象是HttpSessionState類的實例。Session是保存在服務器端的,對每一個登陸到網站的用戶都有一份,是獨有的,而其餘用戶沒法共享。html
咱們來看一個一需求: 須要實時的將服務器的運行狀態輸出到當前登錄的客戶端,創建長鏈接而且做實時輸出。 而後就有了下面這個Action。java
Boolean isOnline = true; public ActionResult Index() { #region 滾動條控制 Response.Write("<html onclick=\"clearInterval(i_1);\" ondblclick =\"reInterval()\"><head><title>服務器實時監控</title></head>"); Response.Write("<script type=\"text/javascript\">"); Response.Write("function scrollWindow() { document.body.scrollTop = document.body.scrollHeight; }"); Response.Write("function reInterval() { i_1 = setInterval('scrollWindow()', 50); }"); Response.Write("i_1 = setInterval('scrollWindow()', 50);"); Response.Write("scrollWindow();"); Response.Write("</script> "); Response.Flush(); #endregion Dictionary<int, string> dicColor = new Dictionary<int, string>() { {0,"#0000FF"}, // 藍色 {1,"#FF3333"}, // 紅色 {2,"#FFFF00"}, // 黃色 {3,"#FF3EFF"}, {4,"#0000FF"}, {5,"#0000FF"} }; DebugCallback callback = new DebugCallback(delegate(int type, string str) { if (dicColor.ContainsKey(type)) { Response.Write("<span style = 'color:" + dicColor[type] + ";'>" + DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss") + "--" + str + "</span> <br />"); } Response.Flush(); }); Log.AddCallBack(callback); while (isOnline) { try { Response.Write("...<br>"); Response.Flush(); } catch { } System.Threading.Thread.Sleep(1000); if (!Response.IsClientConnected) // 鏈接關閉 { Log.RemoveCallBack(callback); Response.Write("</html>"); break; } } return null; }
因爲這個Action是一個長鏈接,它不會斷開鏈接會一直處於請求的狀態,這個時候當咱們再請求同一個Session的其它的Action的時候,發現全部其它的Action都會處於Waiting狀態……好吧,明明是異步併發請求,爲什麼如今卻成了「單線程」工做了呢?很明顯有鎖。瀏覽器
能夠爲本Controller增長如下特性,可是本Controller都不能修改Session了,只能讀取服務器
[SessionState(System.Web.SessionState.SessionStateBehavior.ReadOnly)]
在Web.config 文件裏面添加併發
EnableSessionState="ReadOnly" // 僅僅加載那個阻塞頁面