談?wù)剬?duì).NET中async/await的理解
一、什么是同步?什么是異步?
在.net中,async 和 await 是兩個(gè)關(guān)鍵字,async 關(guān)鍵字用于聲明一個(gè)方法是異步方法,該方法可以包含一個(gè)或多個(gè) await 表達(dá)式。await 關(guān)鍵字是用于在異步方法中等待一個(gè)任務(wù)(Task 或 Task<T>對(duì)象)的完成。在 async 方法中使用 await表達(dá)式時(shí),會(huì)暫停當(dāng)前方法的執(zhí)行,直到等待的任務(wù)完成。在這段時(shí)間內(nèi),主線程可以去執(zhí)行其它操作。
什么是同步:當(dāng)一個(gè)方法被調(diào)用時(shí),調(diào)用者需要等待該方法執(zhí)行完畢后才會(huì)繼續(xù)往下執(zhí)行,我們稱這種方法為同步方法。
什么是異步:當(dāng)一個(gè)方法被調(diào)用時(shí)立即返回,并獲取一個(gè)線程執(zhí)(Task)行該方法內(nèi)部的業(yè)務(wù)邏輯,而調(diào)用者不需要等待這個(gè)方法執(zhí)行完畢,我們稱這種方法為異步方法。
二、async/await是怎么提高性能的?
異步的好處在于非阻塞(調(diào)用線程不會(huì)暫停執(zhí)行去等待子線程完成),因此,我們可以把一些不需要立即使用結(jié)果、耗時(shí)的任務(wù)設(shè)為異步去執(zhí)行,可以提高程序的執(zhí)行效率。
比如,一個(gè)主線程需要執(zhí)行 5 個(gè)方法,假設(shè)每個(gè)方法的分別用時(shí)為 0.1s、0.2s、0.3s、0.4s、0.5s,如果在同步編程中,這個(gè)主線程的執(zhí)行用時(shí)大概為1.5秒。而如果把這5個(gè)方法寫成異步的形式,那么這個(gè)主線程大概用時(shí)為0.5秒。
這是為什么呢?這是因?yàn)椋谕椒椒ㄖ?,主線程在調(diào)用方法時(shí),需要把這個(gè)方法執(zhí)行完成之后再繼續(xù)調(diào)用后續(xù)的方法,主線程執(zhí)行這5個(gè)方法就好比一根線穿5顆珠子一樣,一顆一顆來(lái),所以主線程執(zhí)行所用時(shí)間大概為1.5秒。而在異步方法中,主線程在調(diào)用異步方法時(shí),主線程不會(huì)立即去執(zhí)行異步方法的,而是在遇到異步方法中的 await語(yǔ)句后返回一個(gè)任務(wù)(Task),然后再繼續(xù)調(diào)用后續(xù)的方法,這些任務(wù)的執(zhí)行是由 task創(chuàng)建一個(gè)子線程去執(zhí)行的,主線程執(zhí)行這5個(gè)異步方法就好比5個(gè)人拿5根線同時(shí)穿5顆珠子,所用時(shí)間就是用時(shí)最多的那個(gè),所以主線程執(zhí)行時(shí)間大概為0.5秒。
問(wèn)題:怎么解決在調(diào)用異步函數(shù)時(shí),主線程繼續(xù)向下執(zhí)行后,主線程是怎么回收或管理這個(gè)異步方法的執(zhí)行結(jié)果的。
1、await等待執(zhí)行
public class Demo
{
public async Task DemoAsync()
{
await Task.Delay(1000);
Console.WriteLine("1秒后執(zhí)行");
}
}
public Class Program
{
static async Task Main(string[] args)
{
Demo demo = new Demo();
// 使用 await 等待DemoAsync的執(zhí)行
await demo.DemoAsync();
Console.ReadKey();
}
}2、使用事件
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
demo.OnEvent += (() =>
{
Console.WriteLine("事件訂閱");
});
demo.DemoAsync();
Console.ReadKey();
}
}
public class Demo
{
public event Action OnEvent;
public async Task DemoAsync()
{
Console.WriteLine("開(kāi)始執(zhí)行");
await Task.Delay(1000);
Console.WriteLine("1秒后執(zhí)行");
OnEvent?.Invoke();
}
}3、回調(diào)函數(shù)
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
demo.DemoAsync(() =>
{
Console.WriteLine("回調(diào)函數(shù)");
});
Console.ReadKey();
}
}
public class Demo
{
public async Task DemoAsync(Action callback)
{
Console.WriteLine("開(kāi)始執(zhí)行");
await Task.Delay(1000);
callback?.Invoke();
Console.WriteLine("1秒后執(zhí)行");
}
}4、使用異步方法但不等待結(jié)果
這種方法知識(shí)啟動(dòng)了異步操作而不需要結(jié)果,可以簡(jiǎn)單的調(diào)用異步方法而不使用 await。這種方式不會(huì)阻塞主線程,也不會(huì)處理異步操作的結(jié)果。
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
demo.DemoAsync();
Console.ReadKey();
}
}
public class Demo
{
public async Task DemoAsync()
{
Console.WriteLine("開(kāi)始執(zhí)行");
await Task.Delay(1000);
Console.WriteLine("1秒后執(zhí)行");
}
}5、將異步結(jié)果存儲(chǔ)在變量中
如果想要在某個(gè)時(shí)刻獲取到異步操作中的結(jié)果,可以將異步操作的結(jié)果存儲(chǔ)在變量中,然后再訪問(wèn)它。
internal class Program
{
static void Main(string[] args)
{
Demo demo = new Demo();
var demoResult = demo.DemoAsync();
// 使用 wait等待異步的完成
demoResult.Wait();
if (demoResult.IsCompleted)
{
Console.WriteLine("str執(zhí)行完成");
Console.WriteLine(demoResult.Result);
}
Console.ReadKey();
}
}
public class Demo
{
public async Task<string> DemoAsync()
{
Console.WriteLine("開(kāi)始執(zhí)行");
await Task.Delay(1000);
Console.WriteLine("1秒后執(zhí)行");
return "異步返回結(jié)果";
}
}三、異步到底解決了什么?到底起到了什么樣的作用?
1、提高響應(yīng)性:使用 async 和 await 可以避免等待長(zhǎng)時(shí)間運(yùn)行的操作(如 IO 操作)阻塞主線程,從而提高應(yīng)用程序的響應(yīng)性。
2、簡(jiǎn)化異步操作:async 和 await 使得編寫異步代碼更接近同步代碼的寫法,這降低了異步編程的復(fù)雜性和出錯(cuò)的概率。
3、優(yōu)化資源使用:異步操作允許線程在等待任務(wù)完成時(shí)釋放,這樣可以為其它任務(wù)騰出資源,而不是處于空閑等待狀態(tài)。
四、在使用異步時(shí)的一些問(wèn)題的解決
1、異步的傳遞性問(wèn)題
異步方法的異步效果會(huì)在調(diào)用鏈上向上傳遞的,導(dǎo)致異步方法的調(diào)用鏈上的一些列方法也會(huì)被標(biāo)記為異步。這種情況通常發(fā)生在下面場(chǎng)景中:
調(diào)用異步方法:如果一個(gè)方法調(diào)用了一個(gè)異步方法,那么這個(gè)方法也需要標(biāo)記為 async,并使用 await 等待結(jié)果。返回類型的變化:異步方法通常以 Task 或 Task<T> 類型返回,這意味著調(diào)用這些異步方法的其他方法也需要更新其返回類型以匹配 Task 或 Task<T> 。
異步方法的傳遞性的避免:
1、不使用 await 調(diào)用異步函數(shù):如果在調(diào)用異步函數(shù)時(shí),不需要等待異步函數(shù)的返回結(jié)果,那么可以不適用 await關(guān)鍵字調(diào)用異步函數(shù)。
2、使用 Task.Run 來(lái)啟動(dòng)異步操作:Task.Run 方法可以用來(lái)啟動(dòng)一個(gè)新的異步操作,它會(huì)提供一個(gè)新的任務(wù)來(lái)異步函數(shù),從而避免了異步的傳遞性。
3、使用事件或回調(diào)來(lái)處理異步的結(jié)果:如果異步函數(shù)需要通知調(diào)用者操作已完成,可以使用事件或回調(diào)來(lái)代替直接的 await 調(diào)用。
4、將異步結(jié)果存放在變量中:如果需要等待異步操作的結(jié)果,但又不想立即等待它,可以將異步任務(wù)存儲(chǔ)在變量中,然后在需要訪問(wèn)時(shí)使用 wait 方法來(lái)等待異步的完成。
好記性不然爛筆頭,在學(xué)習(xí)的路上留下點(diǎn)痕跡。希望能給大家?guī)?lái)幫助,也期待你的點(diǎn)贊和討論。
到此這篇關(guān)于談?wù)剬?duì).NET中async/await的理解的文章就介紹到這了,更多相關(guān).net async await內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
asp.net根據(jù)計(jì)算機(jī)MAC地址限定每臺(tái)機(jī)子只能領(lǐng)取一次賬號(hào)
這里只做簡(jiǎn)單演示過(guò)程,請(qǐng)根據(jù)您的實(shí)際情況作適當(dāng)修改!另外我的博客只做自己參考查詢方便用,請(qǐng)各位大神不要沒(méi)事噴我,知道您的技術(shù)高,我是新手正在努力學(xué)習(xí)當(dāng)中,謝謝2012-06-06
ASP.NET MVC下Ajax.BeginForm方式無(wú)刷新提交表單實(shí)例
下面小編就為大家分享一篇ASP.NET MVC下Ajax.BeginForm方式無(wú)刷新提交表單實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-01-01
獲取客戶端IP地址c#/vb.net各自實(shí)現(xiàn)代碼
項(xiàng)目要求獲取客戶端的IP地址,分析并且用c#與vb各自實(shí)現(xiàn)了此要求,有需要的朋友可以了解下啊,希望本文對(duì)你們有所幫助2013-01-01
.NET 6.0 + WPF 使用 Prism 框架實(shí)現(xiàn)導(dǎo)航
Prism是一款專為XAML應(yīng)用程序設(shè)計(jì)的開(kāi)源框架,主要面向WPF和Xamarin Forms等平臺(tái),文章介紹了Prism的基本概念、安裝步驟和使用方法,是開(kāi)發(fā)企業(yè)級(jí)應(yīng)用程序的首選框架,感興趣的朋友跟隨小編一起看看吧2024-09-09
.NET微服務(wù)架構(gòu)CI/CD自動(dòng)構(gòu)建Jenkins+Gitee
這篇文章介紹了.NET使用微服務(wù)架構(gòu)CI/CD自動(dòng)構(gòu)建Jenkins+Gitee的方法,對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2022-01-01
ASP.NET編程時(shí)遇到GridView的一個(gè)問(wèn)題 激發(fā)了未處理的事件"PageIndexChanging&q
今天在寫代碼的時(shí)候遇到一個(gè)很郁悶的問(wèn)題,就是在ASP.NET中通過(guò)編程創(chuàng)建SqlDataSource然后綁定給GridView,在啟用了 GridView自身的分頁(yè)功能之后,點(diǎn)擊分頁(yè)頁(yè)碼會(huì)出現(xiàn)錯(cuò)誤提示:GridView“GridView1”激發(fā)了未處理的事件"PageIndexChanging"……2010-04-04
ASP.NET MVC4中使用Html.DropDownListFor的方法示例
這篇文章主要介紹了ASP.NET MVC4中使用Html.DropDownListFor的方法,結(jié)合實(shí)例形式分析了控制器數(shù)據(jù)源及Html.DropDownListFor顯示操作的相關(guān)技巧,需要的朋友可以參考下2016-08-08
IIS故障(Connections_Refused)問(wèn)題分析及處理
這幾天某地市Web服務(wù)器連續(xù)多次出現(xiàn)故障問(wèn)題(Connections_Refused),正好借這個(gè)案例向大家詳細(xì)介紹下,需要了解的朋友可以參考下2012-12-12

