麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 學院 > 開發設計 > 正文

ASP.NET sync over async(異步中同步,什么鬼?)

2019-11-17 02:11:45
字體:
來源:轉載
供稿:網友

asp.net sync over async(異步中同步,什么鬼?)

async/await 是我們在 ASP.NET 應用程序中,寫異步代碼最常用的兩個關鍵字,使用它倆,我們不需要考慮太多背后的東西,比如異步的原理等等,如果你的 ASP.NET 應用程序是異步到底的,包含數據庫訪問異步、網絡訪問異步、服務調用異步等等,那么恭喜你,你的應用程序是沒問題的,但有一種情況是,你的應用程序代碼比較老,是同步的,但現在你需要調用異步代碼,這該怎么辦呢?有人可能會說,很簡單啊,不是有個 .Result 嗎?但事實真的就這么簡單嗎?我們來探究下。

首先,放出幾篇經典文章:

  • async & await 的前世今生
  • 異步編程 In .NET(中文資料中,寫異步最棒的兩篇文章
  • HttpClient.GetAsync(…) never returns when using await/async
  • Don't Block on Async Code(下面測試中的第三種情況
  • Should I expose synchronous wrappers for asynchronous methods?(sync over async 透徹

上面文章的內容,我們后面會說。光看不練假把式,所以,如果真正要體會 sync over async,我們還需要自己動手進行測試:

  • 1. 異步調用使用 .Result,同步調用使用 .Result
  • 2. 異步調用使用 await,同步調用使用 Task.Run
  • 3. 異步調用使用 await,同步調用使用 .Result
  • 4. 異步調用使用 Task.Run,同步調用使用 .Result
  • 5. 異步調用使用 await .ConfigureAwait(true),同步調用使用 .Result
  • 6. 異步調用使用 await .ConfigureAwait(false),同步調用使用 .Result
  • 7. 異步調用使用 await,異步調用使用 await
  • 8. 測試總結

先說明一下,在測試代碼中,異步調用使用的是 HttpClient.GetAsync 方法,并且測試請求執行兩次,關于具體的分析,后面再進行說明。

1. 異步調用使用 .Result,同步調用使用 .Result

測試代碼:

[Route("")][HttpGet]public string Index(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId1:" + Thread.CurrentThread.ManagedThreadId);    var result = Test();    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId4:" + Thread.CurrentThread.ManagedThreadId);    return result;}public static string Test(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId2:" + Thread.CurrentThread.ManagedThreadId);    using (var client = new HttpClient())    {        var response = client.GetAsync(url).Result;        System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId3:" + Thread.CurrentThread.ManagedThreadId);        return response.Content.ReadAsStringAsync().Result;    }}

輸出結果:

Thread.CurrentThread.ManagedThreadId1:13Thread.CurrentThread.ManagedThreadId2:13Thread.CurrentThread.ManagedThreadId3:13Thread.CurrentThread.ManagedThreadId4:13Thread.CurrentThread.ManagedThreadId1:6Thread.CurrentThread.ManagedThreadId2:6Thread.CurrentThread.ManagedThreadId3:6Thread.CurrentThread.ManagedThreadId4:6

簡單總結:同步代碼中調用異步,上面的測試代碼應該是我們最常寫的,為什么沒有出現線程阻塞,頁面卡死的情況呢?而且代碼中調用了 GetAsync,為什么請求線程只有一個?后面再說,我們接著測試。

2. 異步調用使用 await,同步調用使用 Task.Run

測試代碼:

[Route("")][HttpGet]public string Index(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId1:" + Thread.CurrentThread.ManagedThreadId);    var result = Task.Run(() => Test2()).Result;    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId4:" + Thread.CurrentThread.ManagedThreadId);    return result;}public static async Task<string> Test2(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId2:" + Thread.CurrentThread.ManagedThreadId);    using (var client = new HttpClient())    {        var response = await client.GetAsync(url);        System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId3:" + Thread.CurrentThread.ManagedThreadId);        return await response.Content.ReadAsStringAsync();    }}

輸出結果:

Thread.CurrentThread.ManagedThreadId1:6Thread.CurrentThread.ManagedThreadId2:7Thread.CurrentThread.ManagedThreadId3:11Thread.CurrentThread.ManagedThreadId4:6Thread.CurrentThread.ManagedThreadId1:6Thread.CurrentThread.ManagedThreadId2:7Thread.CurrentThread.ManagedThreadId3:12Thread.CurrentThread.ManagedThreadId4:6

簡單總結:根據上面的輸出結果,我們發現,在一個請求過程中,總共會出現三個線程,一個是開始的請求線程,接著是 Task.Run 創建的一個線程,然后是異步方法中 await 等待的執行線程,需要注意的是,ManagedThreadId1 和 ManagedThreadId4 始終是一樣的。

3. 異步調用使用 await,同步調用使用 .Result

測試代碼:

[Route("")][HttpGet]public string Index(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId1:" + Thread.CurrentThread.ManagedThreadId);    var result = Test3().Result;    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId4:" + Thread.CurrentThread.ManagedThreadId);    return result;}public static async Task<string> Test3(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId2:" + Thread.CurrentThread.ManagedThreadId);    using (var client = new HttpClient())    {        var response = await client.GetAsync(url);        System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId3:" + Thread.CurrentThread.ManagedThreadId);        return await response.Content.ReadAsStringAsync();    }}

輸出結果:

Thread.CurrentThread.ManagedThreadId1:5Thread.CurrentThread.ManagedThreadId2:5

簡單總結:首先,頁面是卡死狀態,ManagedThreadId3 并沒有輸出,也就是執行到 await client.GetAsync 的時候,線程就阻塞了。

4. 異步調用使用 Task.Run,同步調用使用 .Result

測試代碼:

[Route("")][HttpGet]public string Index(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId1:" + Thread.CurrentThread.ManagedThreadId);    var result = Test4().Result;    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId4:" + Thread.CurrentThread.ManagedThreadId);    return result;}public static async Task<string> Test4(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId2:" + Thread.CurrentThread.ManagedThreadId);    return await Task.Run(() =>    {        Thread.Sleep(1000);        System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId3:" + Thread.CurrentThread.ManagedThreadId);        return "xishuai";    });}

輸出結果:

Thread.CurrentThread.ManagedThreadId1:6Thread.CurrentThread.ManagedThreadId2:6Thread.CurrentThread.ManagedThreadId3:7

簡單總結:和第三種情況一樣,頁面也是卡死狀態,但不同的是,ManagedThreadId3 是輸出的,測試它的主要目的是和第三種情況形成對比,以便了解 HttpClient.GetAsync 中到底是什么鬼?

5. 異步調用使用 await .ConfigureAwait(true),同步調用使用 .Result

測試代碼:

[Route("")][HttpGet]public string Index(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId1:" + Thread.CurrentThread.ManagedThreadId);    var result = Test5().Result;    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId4:" + Thread.CurrentThread.ManagedThreadId);    return result;}public static async Task<string> Test5(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId2:" + Thread.CurrentThread.ManagedThreadId);    using (var client = new HttpClient())    {        var task = client.GetAsync(url);        var response = await task.ConfigureAwait(true);        System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId3:" + Thread.CurrentThread.ManagedThreadId);        return await response.Content.ReadAsStringAsync();    }}

輸出結果:

Thread.CurrentThread.ManagedThreadId1:6Thread.CurrentThread.ManagedThreadId2:6

簡單總結:和上面兩種情況一樣,頁面也是卡死狀態,它的效果和第三種完全一樣,ManagedThreadId3 都沒有輸出的。

6. 異步調用使用 await .ConfigureAwait(false),同步調用使用 .Result

測試代碼:

[Route("")][HttpGet]public string Index(){    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId1:" + Thread.CurrentThread.ManagedThreadId);    var result = Test6().Result;    System.Diagnostics.Debug.WriteLine("Thread.CurrentThread.ManagedThreadId4:" + Thread.CurrentThread.ManagedThreadId);    return result;}publ
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 黄色aaa视频 | 久久久久久三区 | 婷婷中文字幕一区二区三区 | www.54271.com | 国产一区二区三区四区在线 | 污视频在线免费播放 | 国产一级一国产一级毛片 | 一本色道久久综合狠狠躁篇适合什么人看 | 成人福利视频在线观看 | 美女网站色免费 | 国产一区视频在线观看免费 | 国产亚洲精彩视频 | 欧美级毛片 | 久久99久久98精品免观看软件 | 成人毛片免费看 | www噜噜偷拍在线视频 | 午夜视频在线观看免费视频 | 伦一区二区三区中文字幕v亚洲 | 国产成人高清成人av片在线看 | 国产午夜精品久久久久婷 | 免费午夜视频 | 真人一级毛片免费 | 99精品欧美一区二区 | 亚洲成人福利在线 | 夜夜看 | 免费99热在线观看 | 亚洲视频高清 | 91成人在线免费 | 特级a欧美做爰片毛片 | 55夜色66夜色国产精品视频 | 欧美成人黄色小视频 | 一级国产电影 | 欧美精品成人一区二区三区四区 | 青热久思思 | 中文字幕精品亚洲 | 亚洲精品免费播放 | 成人午夜免费看 | 国产日韩在线 | 久久艹精品 | 久久久久久久爱 | 黄色美女网站免费看 |