国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁(yè) > 學(xué)院 > 開(kāi)發(fā)設(shè)計(jì) > 正文

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

2019-11-17 02:11:45
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

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

async/await 是我們?cè)?ASP.NET 應(yīng)用程序中,寫(xiě)異步代碼最常用的兩個(gè)關(guān)鍵字,使用它倆,我們不需要考慮太多背后的東西,比如異步的原理等等,如果你的 ASP.NET 應(yīng)用程序是異步到底的,包含數(shù)據(jù)庫(kù)訪問(wèn)異步、網(wǎng)絡(luò)訪問(wèn)異步、服務(wù)調(diào)用異步等等,那么恭喜你,你的應(yīng)用程序是沒(méi)問(wèn)題的,但有一種情況是,你的應(yīng)用程序代碼比較老,是同步的,但現(xiàn)在你需要調(diào)用異步代碼,這該怎么辦呢?有人可能會(huì)說(shuō),很簡(jiǎn)單啊,不是有個(gè) .Result 嗎?但事實(shí)真的就這么簡(jiǎn)單嗎?我們來(lái)探究下。

首先,放出幾篇經(jīng)典文章:

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

上面文章的內(nèi)容,我們后面會(huì)說(shuō)。光看不練假把式,所以,如果真正要體會(huì) sync over async,我們還需要自己動(dòng)手進(jìn)行測(cè)試:

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

先說(shuō)明一下,在測(cè)試代碼中,異步調(diào)用使用的是 HttpClient.GetAsync 方法,并且測(cè)試請(qǐng)求執(zhí)行兩次,關(guān)于具體的分析,后面再進(jìn)行說(shuō)明。

1. 異步調(diào)用使用 .Result,同步調(diào)用使用 .Result

測(cè)試代碼:

[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;    }}

輸出結(jié)果:

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

簡(jiǎn)單總結(jié):同步代碼中調(diào)用異步,上面的測(cè)試代碼應(yīng)該是我們最常寫(xiě)的,為什么沒(méi)有出現(xiàn)線程阻塞,頁(yè)面卡死的情況呢?而且代碼中調(diào)用了 GetAsync,為什么請(qǐng)求線程只有一個(gè)?后面再說(shuō),我們接著測(cè)試。

2. 異步調(diào)用使用 await,同步調(diào)用使用 Task.Run

測(cè)試代碼:

[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();    }}

輸出結(jié)果:

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

簡(jiǎn)單總結(jié):根據(jù)上面的輸出結(jié)果,我們發(fā)現(xiàn),在一個(gè)請(qǐng)求過(guò)程中,總共會(huì)出現(xiàn)三個(gè)線程,一個(gè)是開(kāi)始的請(qǐng)求線程,接著是 Task.Run 創(chuàng)建的一個(gè)線程,然后是異步方法中 await 等待的執(zhí)行線程,需要注意的是,ManagedThreadId1 和 ManagedThreadId4 始終是一樣的。

3. 異步調(diào)用使用 await,同步調(diào)用使用 .Result

測(cè)試代碼:

[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();    }}

輸出結(jié)果:

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

簡(jiǎn)單總結(jié):首先,頁(yè)面是卡死狀態(tài),ManagedThreadId3 并沒(méi)有輸出,也就是執(zhí)行到 await client.GetAsync 的時(shí)候,線程就阻塞了。

4. 異步調(diào)用使用 Task.Run,同步調(diào)用使用 .Result

測(cè)試代碼:

[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";    });}

輸出結(jié)果:

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

簡(jiǎn)單總結(jié):和第三種情況一樣,頁(yè)面也是卡死狀態(tài),但不同的是,ManagedThreadId3 是輸出的,測(cè)試它的主要目的是和第三種情況形成對(duì)比,以便了解 HttpClient.GetAsync 中到底是什么鬼?

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

測(cè)試代碼:

[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();    }}

輸出結(jié)果:

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

簡(jiǎn)單總結(jié):和上面兩種情況一樣,頁(yè)面也是卡死狀態(tài),它的效果和第三種完全一樣,ManagedThreadId3 都沒(méi)有輸出的。

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

測(cè)試代碼:

[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
發(fā)表評(píng)論 共有條評(píng)論
用戶名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 富阳市| 夹江县| 隆化县| 视频| 白玉县| 温泉县| 东乡族自治县| 新乡市| 阜新市| 横山县| 尚志市| 峨眉山市| 石泉县| 称多县| 噶尔县| 四川省| 民乐县| 高邮市| 衡阳县| 合水县| 新余市| 吉林省| 应用必备| 土默特右旗| 山丹县| 西乌| 潢川县| 五台县| 宁德市| 泰安市| 兴业县| 区。| 鄂温| 拉萨市| 积石山| 和顺县| 横山县| 社会| 确山县| 大港区| 通化市|