1.前提
熟練掌握Task並行編程。
2.用Task並行解釋async和await異步
因為控制台有多線程操作的優化,因此這里選擇winform來做示例。
測試代碼如下所示:
有三個textbox,一個button
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;
namespace TestAsyncAwait
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Button1_Click(object sender, EventArgs e)
{
TestAsync();
textBox3.Text = "333";
}
private async void TestAsync()
{
//Thread.Sleep(5000);//依然阻塞
await Task.Run(() =>
{
Thread.Sleep(2000);
this.Invoke((EventHandler)delegate { textBox1.Text = "1"; });
Thread.Sleep(2000);
});
this.Invoke((EventHandler)delegate { textBox2.Text = "22"; });
}
}
}
顯示的順序是:333,1,22
如果在設置textbox顯示內容之前,通過Thread.CurrentThread.ManagedThreadId屬性來獲取當前線程ID。
可以得到textbox3所在為主線程,await之前也在主線程,await中和await后為新線程,這也是為什么在textbox1和textbox2的text加上invoke的原因。
簡單來時,實際上async和await就是表示,遇到await之后,函數直接返回,然后剩下的部分等同於在一個新線程中運行。
使用Task並行編程的解釋代碼如下,將button按鈕的click事件與TestAsync函數統一成TestTask函數
private void TestTask()
{
Task.Run(() =>
{
Task task = Task.Run(() =>
{
Thread.Sleep(2000);
this.Invoke((EventHandler)delegate { textBox1.Text = "1"; });
Thread.Sleep(2000);
});
Task.WaitAll(task);
this.Invoke((EventHandler)delegate { textBox2.Text = "22"; });
});
textBox3.Text = "333";
}
當然,上述代碼也不完全等價async和await,只不過在實現功能上來說,沒有差別。
具體的差別表現為,waitall之前的線程與waitall之后所在線程不在同一個線程。這個差別也揭示了async和await的另外一個優勢,那就是節約線程,內部實現了線程池優化。
3.總結
如果你懂得Task並行編程或者Thread多線程編程,其實async和await的原理是不難的,沒有什么神乎其神的操作。
async和await作為C#異步編程的語法糖,具有無可匹敵的優勢,但是很多時候很多人不能理解用法,相比較而言直接使用Task並行編程會更加易懂。
我的建議是,如果是新項目可以使用async和await,讓自己的代碼更簡潔;如果是老項目維護,建議還是使用Task的方式維護,容易讀懂。