日本好好热aⅴ|国产99视频精品免费观看|日本成人aV在线|久热香蕉国产在线

  • <cite id="ikgdy"><table id="ikgdy"></table></cite>
    1. 西西軟件園多重安全檢測下載網(wǎng)站、值得信賴的軟件下載站!
      軟件
      軟件
      文章
      搜索

      首頁編程開發(fā)ASP.NET → async、await在ASP.NET中線程死鎖的解決方法

      async、await在ASP.NET中線程死鎖的解決方法

      相關軟件相關文章發(fā)表評論 來源:西西整理時間:2013/5/13 9:31:18字體大。A-A+

      作者:西西TS點擊:333次評論:0次標簽: async

      Asynchronous XXXV1.0安卓版
      • 類型:休閑益智大。32.1M語言:英文 評分:10.0
      • 標簽:
      立即下載

      C# 5.0中引入了async 和 await。這兩個關鍵字可以讓你更方便的按照同步的方式寫出異步代碼。也就是說使你更方便的異步編程。

      下面演示使用async,await的方式

      第一步:將 VS2010 升級到 VS2010 sp1.

      第二步:下載Async CTP,進行安裝

      第三步:為應用程序添加AsyncCTPLibrary引用,如下:

      OK,將上面的SumPageSizes 方法修改如下:

      public async Task<int> SumPageSizesAsync2(IList<Uri> uris){    var tasks = uris.Select(uri => new WebClient().DownloadDataTaskAsync(uri));    var data = await TaskEx.WhenAll(tasks);    return await TaskEx.Run(() => 
          {        return data.Sum(s => s.Length);    });}

      在AsyncCTPLibrary.dll中,微軟為一些類提供了擴展,如下:

      WebClient的擴展如下:

      可以看到基本上為每個Download 都增加了一個XXXTaskAsync 的擴展方法。

      async、await線程死鎖的故事及解決方法:

      早就聽說.Net4.5里有一對好基友async和await,今兒我迫不及待地拿過來爽了一把。尼瑪就悲劇了啊。

      場景重構(gòu)

       1 public ActionResult Index(string ucode)
       2 {
       3     string userInfo = GetUserInfo(ucode).Result;
       4     ViewData["UserInfo"] = userInfo;
       5     return View();
       6 }
       7 
       8 async Task<string> GetUserInfo(string ucode)
       9 {
      10     HttpClient client = new HttpClient();
      11     var httpContent = new FormUrlEncodedContent(new Dictionary<string, string>()
      12     {
      13         {"ucode", ucode}
      14     });
      15     string uri = "http://www.xxxx.com/user/get";
      16     var response = await client.PostAsync(uri, httpContent);
      17     return response.Content.ReadAsStringAsync().Result;
      18 }

      上述代碼是對真實案例的簡化,即通過第三方OPenAPI獲取用戶信息,然后展示在Index頁中,很簡單。我點運行之后,發(fā)現(xiàn)執(zhí)行到var response = await client.PostAsync(uri, httpContent);黃色小箭頭進入到這句代碼之后就消失的無影無蹤,我等了半宿,然后……然后就沒有然后了,沒有異常,只有寂寞。

      我首先考慮到是不是HttpClient引起的(之前使用HttpWebRequest.GetResponse能按預期執(zhí)行,因此不會是http://www.xxxx.com/user/get這個API的問題,且當時并沒有想到會是線程問題),查閱了很多資料,對代碼進行反復修改,問題依舊。后來我鬼使神差地將最后兩行改為:

      1 var response = client.PostAsync(uri, httpContent).Result.Content.ReadAsStringAsync().Result;
      2 return response;

      問題竟然神奇的消失了,當Index頁面展現(xiàn)在我眼前的時候,我心說這不是玩我呢吧。我安慰自己說這或許是.NET框架的某個不為人知的bug,倒霉被我遇到,不管了洗洗睡吧。經(jīng)過一個晚上的折騰,累得夠嗆,于是我很快就進入了夢鄉(xiāng)。夢中考英語,試卷上只能看到密密麻麻的a,我急得滿頭大汗,再仔細一看,滿滿的就兩個單詞:async和await。我一下驚醒了。

      async和await

      關于async和await,這兄弟倆是對異步編程的語法簡化。談到異步,就涉及到線程和邏輯執(zhí)行順序,看下面代碼就一清二楚了。

       1 class Program
       2 {
       3     static void Main(string[] args)
       4     {
       5         Console.WriteLine("step1,線程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
       6 
       7         AsyncDemo demo = new AsyncDemo();
       8         //demo.AsyncSleep().Wait();//Wait會阻塞當前線程直到AsyncSleep返回
       9         demo.AsyncSleep();//不會阻塞當前線程
      10 
      11         Console.WriteLine("step5,線程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
      12         Console.ReadLine();
      13     }
      14 }
      15 
      16 public class AsyncDemo
      17 {
      18 
      19     public async Task AsyncSleep()
      20     {
      21         Console.WriteLine("step2,線程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
      22 
      23         //await關鍵字表示等待Task.Run傳入的邏輯執(zhí)行完畢,此時(等待時)AsyncSleep的調(diào)用方能繼續(xù)往下執(zhí)行
      24         //Task.Run將開辟一個新線程執(zhí)行指定邏輯
      25         await Task.Run(() => Sleep(10));
      26 
      27         Console.WriteLine("step4,線程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
      28     }
      29 
      30     private void Sleep(int second)
      31     {
      32         Console.WriteLine("step3,線程ID:{0}", System.Threading.Thread.CurrentThread.ManagedThreadId);
      33 
      34         Thread.Sleep(second * 1000);
      35     }
      36 
      37 }

      運行結(jié)果:

      注意step2和step4雖然在同一個方法內(nèi)部,但它們的運行線程是不同的,step4與step3一樣使用Task.Run開辟的新線程。注意:假如我們在Sleep里再次使用Task.Run又開辟了新線程,假設ID為10,并通過await關鍵詞修飾,那么step4將運行在線程10。假如將第8、9行注釋互換:

      1 demo.AsyncSleep().Wait();//Wait會阻塞當前線程直到AsyncSleep返回
      2 //demo.AsyncSleep();//不會阻塞當前線程

      即人為控制異步邏輯同步返回,其實這和之前獲取用戶信息的場景是一樣一樣的,猜想是在執(zhí)行step2或step3后再無后續(xù)輸出。運行結(jié)果:

      看來“事與愿違”。那么這里怎么沒有出現(xiàn)之前的問題呢?

      提問:再將第25行改為Task.Run(() => Sleep(10)).Wait();這時候會輸出什么呢,或者說step4的輸出線程ID是多少?Task.Wait();和await不一樣,它會阻塞當前線程(而不管內(nèi)部邏輯是否開辟了新的線程)。運行結(jié)果:

      可得step4仍運行在主線程。

      線程死鎖

      引起線程死鎖的原因有很多。在ASP.NET[ MVC]的場景中,涉及到一個概念就是AspNetSynchronizationContext,它同時只能被一個線程獨占。結(jié)合async和await的特性,回到本文開頭的代碼:

       1 public ActionResult Index(string ucode)
       2 {
       3     string userInfo = GetUserInfo(ucode).Result;//線程A阻塞,等待GetUserInfo返回,當前上下文AspNetSynchronizationContext
       4     ViewData["UserInfo"] = userInfo;
       5     return View();
       6 }
       7 
       8 async Task<string> GetUserInfo(string ucode)
       9 {
      10     HttpClient client = new HttpClient();
      11     var httpContent = new FormUrlEncodedContent(new Dictionary<string, string>()
      12     {
      13         {"ucode", ucode}
      14     });
      15     string uri = "http://www.xxxx.com/user/get";     //client.PostAsync在其內(nèi)部開辟新線程(設為B)異步執(zhí)行,注意await并不會阻塞當前線程,而是將控制權返回方法調(diào)用方,這里是Index Action
      16     var response = await client.PostAsync(uri, httpContent);     //client.PostAsync返回,但下列代碼仍運行在線程B。當前方法企圖重入AspNetSynchronizationContext,死鎖產(chǎn)生在這里17     return response.Content.ReadAsStringAsync().Result;
      18 }

      解決方法:

      var response= await client.PostAsync(uri, httpContent).ConfigureAwait(false);//第16行

      調(diào)用方使用await調(diào)用async方法,而非GetResult、Task.Resul、Task.Wait;//第3行

      使用client.PostAsync(uri, httpContent).Result.Content.ReadAsStringAsync().Result。//阻塞當前線程,而非將控制權返回給調(diào)用方,如前所述

        相關評論

        閱讀本文后您有什么感想? 已有人給出評價!

        • 8 喜歡喜歡
        • 3 頂
        • 1 難過難過
        • 5 囧
        • 3 圍觀圍觀
        • 2 無聊無聊

        熱門評論

        最新評論

        發(fā)表評論 查看所有評論(0)

        昵稱:
        表情: 高興 可 汗 我不要 害羞 好 下下下 送花 屎 親親
        字數(shù): 0/500 (您的評論需要經(jīng)過審核才能顯示)