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

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

關(guān)于async和await的一些誤區(qū)

2019-11-14 16:31:12
字體:
來(lái)源:轉(zhuǎn)載
供稿:網(wǎng)友

微軟的MSDN說(shuō)async和await是“異步”,但是不少人(包括筆者自己)有一些誤區(qū)需要澄清:為什么await語(yǔ)句之后沒(méi)有執(zhí)行?不是異步嗎?

  【示例代碼】

public partial class Form1 : Form    {        public async Task PRocessing()        {            await Task.Delay(5000);            label1.Text = "Succuessful";        }        public Form1()        {            InitializeComponent();                    }        private async void button1_Click(object sender, EventArgs e)        {            await Processing();            MessageBox.Show("Button's event completed");        }    }

很多人(包括筆者)一開(kāi)始會(huì)覺(jué)得異步好像類(lèi)似多線(xiàn)程一樣,到await的時(shí)候會(huì)在后臺(tái)先開(kāi)啟一個(gè)線(xiàn)程執(zhí)行任務(wù),隨后主線(xiàn)程(這里是UI線(xiàn)程)將自動(dòng)執(zhí)行后面的部分(即彈出“Button's event completed”的消息框)。

其實(shí)這個(gè)理解是錯(cuò)誤的。async和await的本質(zhì)其實(shí)是“yield return”和“LINQ”的“迭代式”等待。我們應(yīng)該清楚一點(diǎn):那就是你寫(xiě)了LINQ語(yǔ)句:

var results = from ……              select ……;foreach(var r in results){  ……}

當(dāng)你下斷點(diǎn)你會(huì)發(fā)覺(jué)results并不會(huì)立即執(zhí)行,直到使用到results的地方(例子中也就是foreach這里)才會(huì)被執(zhí)行(此時(shí)黃色跟蹤調(diào)試的光棒又會(huì)折回到var results……這里,然后等到results執(zhí)行完畢之后才真正進(jìn)入foreach進(jìn)行執(zhí)行)。

所以,async/await和LINQ的這種“迭代式”的“異步操作”是異曲同工的。只不過(guò)async/await本質(zhì)是返回一個(gè)Task而已,而Task又是異步的(因?yàn)門(mén)ask本質(zhì)就是一個(gè)線(xiàn)程),所以真正執(zhí)行到(使用到async方法的時(shí)候)帶有await的方法的時(shí)候,后臺(tái)才會(huì)真正開(kāi)啟一個(gè)線(xiàn)程去執(zhí)行任務(wù)。此時(shí)主線(xiàn)程會(huì)等待這個(gè)Task線(xiàn)程直到其執(zhí)行完畢(IsComplete屬性為T(mén)rue為止)。所以界面是不會(huì)卡頓的。

所以,await是Task的異步等待而已,并不是我們所謂的“異步操作”;拿它和LINQ作對(duì)比,你會(huì)發(fā)現(xiàn)LINQ執(zhí)行順序和它一致,只不過(guò)LINQ沒(méi)有異步等待(當(dāng)然沒(méi)有!又沒(méi)有開(kāi)啟線(xiàn)程啥的……)。

我們進(jìn)一步可以這樣對(duì)比:

LINQ:變量 = LINQ語(yǔ)句(表達(dá)式)

           等到使用LINQ變量的時(shí)候才折返到LINQ語(yǔ)句處真正執(zhí)行LINQ語(yǔ)句。

異步等待:變量 = 異步方法

            等到使用await+異步方法的時(shí)候才會(huì)折返到該異步方法處,開(kāi)啟線(xiàn)程真正執(zhí)行異步方法,主線(xiàn)程被掛起(但不會(huì)造成界面死掉),直至子線(xiàn)程Task任務(wù)完全執(zhí)行完畢為止。

在LINQ中,你如果需要立即執(zhí)行,可以使用擴(kuò)展方法:

var results = (from ……              select ……).ToList();

因?yàn)榱⒓词褂玫搅诉@個(gè)LINQ語(yǔ)句,所以會(huì)被立即執(zhí)行。

同樣地,異步等待也可以變成類(lèi)似Wait一樣的同步等待:

private async void button1_Click(object sender, EventArgs e)        {            Processing().GetAwaiter().GetResult();            MessageBox.Show("Button's event completed");        }

因?yàn)镻rocessing本來(lái)就返回Task,當(dāng)然也可以使用Wait進(jìn)行同步等待。

參考文獻(xiàn):http://blog.csdn.net/ma_jiang/article/details/37884915


發(fā)表評(píng)論 共有條評(píng)論
用戶(hù)名: 密碼:
驗(yàn)證碼: 匿名發(fā)表
主站蜘蛛池模板: 肇源县| 天镇县| 九寨沟县| 聂荣县| 会昌县| 东阳市| 韶山市| 太白县| 吉木萨尔县| 凤冈县| 临洮县| 改则县| 钟山县| 邹城市| 固始县| 隆德县| 封开县| 满洲里市| 宁海县| 大连市| 岑巩县| 介休市| 泰兴市| 镇安县| 葫芦岛市| 四川省| 阳山县| 志丹县| 喜德县| 隆昌县| 咸宁市| 沭阳县| 锡林浩特市| 南陵县| 敖汉旗| 县级市| 锡林郭勒盟| 理塘县| 九台市| 阳城县| 竹溪县|