<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Asp.Net在多線程環境下的狀態存儲問題

            在應用開發中,我們經常需要設置一些上下文(Context)信息,這些上下文信息一般基于當前的會話(Session),比如當前登錄用戶的個人信息;或者基于當前方法調用棧,比如在同一個調用中涉及的多個層次之間數據。

            在.Net中,常用的有以下三種方法來實現這個特性.

            HttpContext.Current.Session或HttpContext.Currnet.Items是大家使用的最多的方式.

            [ThreadStatic]方式可以存儲單個線程的共享狀態.

            System.Runtime.Remoting.Messaging.CallContext類則可以存儲一個邏輯線程的共享狀態,即主線程和其所有子線程都共享這段內存.

            在Asp.Net中通常使用第一種方式.但是魚李寫了一篇文章,指出HttpContext.Current并非無處不在,只有是由請求發起的線程,HttpContext.Current才不為空.換句話說,在多線程環境下, 比如是由定時器發起的線程,Currnet屬性就為空,這時依賴于它的相關功能便無法完成.比如使用它獲取文件路徑等.

            魚李給出了兩種解決方法,將HttpContext.Current保存在外部變量中,或者通過函數參數傳遞.

            我個人認為這只是折中的解決辦法,它沒有在解決問題的同時保待簡單性,即程序員不需關心HttpContext.Current的保存位置與傳遞方式,而直接便可使用.

            后臺又查到了A大的一篇文章.給出了保存下文(Context)信息的通用解決方案,簡單來說,在桌面環境使用System.Runtime.Remoting.Messaging.CallContext類,在Web環境下使用常規的HttpContext.Current,但是同時在System.Runtime.Remoting.Messaging.CallContext類中也保存了一個對它的引用.在線程切換時,依照.Net的設計,System.Runtime.Remoting.Messaging.CallContext類中保存的實現了ILogicalThreadAffinative接口的數據都會自動被復制到新的線程中,即完成了上下文傳遞.

            A大給出了一個精妙的解決方案,但卻沒有解決我所有的疑問,比如48L的園友就提出了"請教一下,callcontxt無論是那種應用都可以使用,為什么還要使用HttpSessionState?".于是我繼續探究.終于在一篇老外的博文中找到了答案.

            在那篇文章里,老外做了一個試驗.有兩個頁面,均在其構造函數與Page_Load中使用上面三種方式記錄當前線程Id,但是在名為slow的頁面中人為讓處理線程睡一下來模擬耗時操作.首先訪問slow頁面,在其返回前快速多次刷新fast頁面.最終的打印結果讓作者surprise了一下.對于slow頁面,執行構造函數的線程與Page_Load的線程保持一致,三種方式的記錄結果也沒有丟失,但是在fast頁面中,有可能出現執行構造函數的線程與Page_Load的線程不一致,三種方式的記錄結果也丟失了兩種:僅剩下HttpContext了.

            我的重現代碼如下,增加了LogicalSetData方式,后文再表:

      public partial class Fast : System.Web.UI.Page
      {
          [ThreadStatic]
          private static string info = string.Empty;
      
          public Fast()
          {
              info = "fast ctor:" + Thread.CurrentThread.ManagedThreadId;
              CallContext.SetData("id", Thread.CurrentThread.ManagedThreadId);
              CallContext.LogicalSetData("id1", Thread.CurrentThread.ManagedThreadId);
              Items["id2"] = Thread.CurrentThread.ManagedThreadId;
          }
      
          protected void Page_Load(object sender, EventArgs e)
          {
              Response.Write("ThreadStatic:" + info);
              info = string.Empty;
              Response.Write("<br />");
              Response.Write("CallContext.SetData:" + CallContext.GetData("id"));
              Response.Write("<br />");
              Response.Write("CallContext.LogicalSetData:" + CallContext.LogicalGetData("id1"));
              Response.Write("<br />");
              Response.Write("Items:" + Items["id2"]);
              Response.Write("<br />");
              Response.Write("<br />fast page_load:" + Thread.CurrentThread.ManagedThreadId);
          }
      }
      
      public partial class Slow : System.Web.UI.Page
      {
          [ThreadStatic]
          private static string info = string.Empty;
      
          public Slow()
          {
              Thread.Sleep(1000);
              info = "slow ctor:" + Thread.CurrentThread.ManagedThreadId;
              CallContext.SetData("id", Thread.CurrentThread.ManagedThreadId);
              CallContext.LogicalSetData("id1", Thread.CurrentThread.ManagedThreadId);
              Items["id2"] = Thread.CurrentThread.ManagedThreadId;
          }
      
          protected void Page_Load(object sender, EventArgs e)
          {
              Thread.Sleep(1000);
              Response.Write("ThreadStatic:" + info);
              info = string.Empty;
              Response.Write("<br />");
              Response.Write("CallContext.SetData:" + CallContext.GetData("id"));
              Response.Write("<br />");
              Response.Write("CallContext.LogicalSetData:" + CallContext.LogicalGetData("id1"));
              Response.Write("<br />");
              Response.Write("Items:" + Items["id2"]);
              Response.Write("<br />");
              Response.Write("<br />slow page_load:" + Thread.CurrentThread.ManagedThreadId);
          }
      }

       

            執行結果如下:

            從博文中獲知,這是完全正常的執行結果, Asp.Net開發團隊還為其起了個好聽的名字:Thread-Agile.這個特性表明,即使你使用常規的Asp.Net開發方式,也不能保證所有的代碼一定會在同一線程中執行.從其它的文章中獲知,這是與負載有關的.負載越大,越有可能產生多線程.每當程序進入一個新的線程中執行時,Asp.Net會手動(是使用額外代碼實現的,不是.Net自帶的機制)將HttpContext對象復制到新線程中.一方面這能將多線程完全透明,讓程序員使用單線程的編程方式編寫多線程程序;另一方面CallContext.SetData與[ThreadStatic]就丟失了.但由于使用LogicalSetData方法存儲的數據其內部都會自動封裝成實現了ILogicalThreadAffinative接口的對象,所以在線程切換時能正常流轉.

            所以,在Asp.Net環境下,除非自己建立一套上下文環境解決方案,否則在該用的情況下還是老老實實使用HttpContext吧.

            歡迎各路朋友指正.

       

            參考

            HttpContext.Current并非無處不在

            如何實現對上下文(Context)數據的統一管理 [提供源代碼下載]

            CallContext和多線程

            HTTPContext across threads

            Do ASP.NET Requests always BeginRequest and EndRequest on the same thread?

            CallContext vs ThreadStatic

            ThreadStatic, CallContext and HttpContext in ASP.Net

            CallContext vs. ThreadStatic vs. HttpContext

            關于線程及CallContext

            多線程編程之計算限制型異步操作

            CallContext.LogicalGetData Vs. CallContext.GetData

      posted @ 2013-06-18 17:56  永遠的阿哲  閱讀(2820)  評論(3)    收藏  舉報
      主站蜘蛛池模板: 蜜臀av在线一区二区三区| 成在线人永久免费视频播放| 亚洲综合小综合中文字幕| 国产精品99中文字幕| √天堂中文www官网在线| 欧美色欧美亚洲高清在线视频| 中文无码乱人伦中文视频在线| 一色屋精品视频在线观看| 蜜臀久久99精品久久久久久| 99福利一区二区视频| 国产精品大全中文字幕| 亚洲AV日韩AV综合在线观看| 日韩中文字幕有码av| 思茅市| 精品人妻伦一二三区久久| 日韩乱码视频一区二区三区| 亚洲 日韩 在线精品| 国产超高清麻豆精品传媒麻豆精品 | 亚洲黄色片一区二区三区| 亚洲中文字幕第二十三页| yw尤物av无码国产在线观看| 狠狠色婷婷久久综合频道日韩| 中文字幕理伦午夜福利片| 秋霞在线观看片无码免费不卡| 后入内射无码人妻一区| 亚洲中文字幕有综合久久| 日韩av第一页在线播放| 欧美成人精精品一区二区三区| 九九热在线免费观看视频| 秋霞人妻无码中文字幕| 在线看av一区二区三区| 日本免费精品| 中文无码精品a∨在线| 亚洲在线一区二区三区四区| 性欧美暴力猛交69hd| 文中字幕一区二区三区视频播放 | 啦啦啦视频在线日韩精品| 97亚洲熟妇自偷自拍另类图片| 亚洲熟妇自偷自拍另欧美| 无遮挡又黄又刺激的视频| 狼人大伊人久久一区二区|