微軟的MSDN說async和await是「異步」,可是很多人(包括筆者本身)有一些誤區須要澄清:爲何await語句以後沒有執行?不是異步嗎?多線程
【示例代碼】異步
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"); } }
不少人(包括筆者)一開始會以爲異步好像相似多線程同樣,到await的時候會在後臺先開啓一個線程執行任務,隨後主線程(這裏是UI線程)將自動執行後面的部分(即彈出「Button's event completed」的消息框)。async
其實這個理解是錯誤的。async和await的本質實際上是「yield return」和「LINQ」的「迭代式」等待。咱們應該清楚一點:那就是你寫了LINQ語句:spa
var results = from …… select ……; foreach(var r in results) { …… }
當你下斷點你會發覺results並不會當即執行,直到使用到results的地方(例子中也就是foreach這裏)纔會被執行(此時黃色跟蹤調試的光棒又會折回到var results……這裏,而後等到results執行完畢以後才真正進入foreach進行執行)。.net
因此,async/await和LINQ的這種「迭代式」的「異步操做」是殊途同歸的。只不過async/await本質是返回一個Task而已,而Task又是異步的(由於Task本質就是一個線程),因此真正執行到(使用到async方法的時候)帶有await的方法的時候,後臺纔會真正開啓一個線程去執行任務。此時主線程會等待這個Task線程直到其執行完畢(IsComplete屬性爲True爲止)。因此界面是不會卡頓的。線程
因此,await是Task的異步等待而已,並非咱們所謂的「異步操做」;拿它和LINQ做對比,你會發現LINQ執行順序和它一致,只不過LINQ沒有異步等待(固然沒有!又沒有開啓線程啥的……)。調試
咱們進一步能夠這樣對比:code
LINQ:變量 = LINQ語句(表達式)orm
等到使用LINQ變量的時候才折返到LINQ語句處真正執行LINQ語句。blog
異步等待:變量 = 異步方法
等到使用await+異步方法的時候纔會折返到該異步方法處,開啓線程真正執行異步方法,主線程被掛起(但不會形成界面死掉),直至子線程Task任務徹底執行完畢爲止。
在LINQ中,你若是須要當即執行,可使用擴展方法:
var results = (from …… select ……).ToList();
由於當即使用到了這個LINQ語句,因此會被當即執行。
一樣地,異步等待也能夠變成相似Wait同樣的同步等待:
private async void button1_Click(object sender, EventArgs e) { Processing().GetAwaiter().GetResult(); MessageBox.Show("Button's event completed"); }
由於Processing原本就返回Task,固然也可使用Wait進行同步等待。
參考文獻:http://blog.csdn.net/ma_jiang/article/details/37884915