使用異步的好處是什么呢?
我認為有如下好處:
1.用戶體驗性好
比如一個表格需要綁定大量數據,整個過程完成需要十幾秒鍾,而用戶希望在這過程中,可以點擊其它地方
(若需要界面不卡死,常用的一種方法是使用backgroundworker (實際上也是異步,新開一個線程來執行,用戶體驗性好了,但是實際執行效率並沒有得到提升),點擊按鈕執行BackgroundWorker.RunWorkerAsync,觸發DoWork事件)
2.提高程序執行速度
假設一個button按鈕里的代碼有三部分,Code1執行需要10秒,Code2執行需要20秒,Code3執行需要30秒,因為程序代碼解讀自上而下,傳統的同步方式會等待每一句代碼執行完成后,才會執行下一句代碼,所以點擊此button后,需要60秒才能全部執行結束,界面卡死消失;
而async/await異步的原理是Code1委托給線程1處理了,主線程不管了,程序繼續往下執行,接着Code2委托給線程2執行,程序繼續往下執行,接着Code3直接處理就好(不用委托異步調用),Button執行時間為最大的一部分,也就是30秒,並且界面不卡死
異步使用
async 提供上下文信息,提示編譯器里面會包含await方法,async必須在返回類型之前,比如private static async Task<int>...

using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Diagnostics; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; namespace WindowsFormsApplication1 { public partial class frmAsync : Form { public frmAsync() { InitializeComponent(); } /// <summary> /// 程序執行時間10秒 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void btnAsync_Click(object sender, EventArgs e) { var count= await GetCountValue(); //如果不加await,因為這是個異步方法,不會等待,變量count得到的值是int類型 MessageBox.Show(count.ToString()); } private async Task<int> GetCountValue() { Stopwatch sw = new Stopwatch(); sw.Start(); //Func<int,int> Func = Calc; //Func(1000); //Task為線程池的封裝模式。 Task<int> result = Task.Run<int>(() => { return Calc(1000); }); //方法沒有參數傳入,有返回值 //Task<string> result2 = Task.Run<string> // (() => { return GetCalc(); }); //await result2; int finialValue = 0; int countValue = 0; //可以在匿名函數里面直接寫方法體 //Task<int> result2 = Task.Run<int>(() => //{ // for (int i = 0; i < 1000; i++) // { // System.Threading.Thread.Sleep(10); // countValue += i; // } // return countValue; //}); //直接執行 for (int i = 0; i < 1000; i++) { System.Threading.Thread.Sleep(10); countValue += i; } await result; // await result2; #region 這樣寫耗時一樣,但是界面會卡死,直到運行結束 //Task[] para = { result, result2 }; //Task.WaitAll(para); #endregion finialValue = countValue + result.Result; sw.Stop(); this.richTextBox1.Text = "最終計算結果:" + finialValue + "異步方法耗時:" + (sw.ElapsedMilliseconds / 1000) + "秒"; return finialValue; } /// <summary> /// 傳統的同步方式,程序執行時間疊加,這里為20秒, /// /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void btnTongbu_Click(object sender, EventArgs e) { Stopwatch sw = new Stopwatch(); sw.Start(); int countValue = 0; int finialValue = 0; int value1 = Calc(1000); //這段代碼體現出winForm是單線程的,我們期望會在執行10秒后,界面上先出現如下提示,在實際執行的時候發現, //會與最終計算結果....的文本值一起出現在richTextBox1上, //雖然 Calc(1000)的值計算出來了,但是線程很忙,緊接着在執行下一段代碼,沒有空去更新richTextBox1控件 this.richTextBox1.Text = "第一階段值:" + value1.ToString(); for (int i = 0; i < 1000; i++) { System.Threading.Thread.Sleep(10); countValue += i; } finialValue = value1 + countValue; sw.Stop(); this.richTextBox1.Text += "最終計算結果:" + finialValue + "同步方法耗時:" + (sw.ElapsedMilliseconds / 1000) + "秒"; } private int Calc(int maxNum) { int sumValue = 0; for (int i = 0; i < maxNum; i++) { System.Threading.Thread.Sleep(10); sumValue += i; } return sumValue; } private static string GetCalc() { //Thread.Sleep(10000); int a = 1000; double b = 0; for (int i = 0; i < a; i++) { System.Threading.Thread.Sleep(10); b += i; } return b.ToString(); } /// <summary> /// Task.Factory.StartNew 程序執行時間20秒 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void button1_Click(object sender, EventArgs e) { Stopwatch sw = new Stopwatch(); sw.Start(); int countValue = 0; Task<int> result = Task.Factory.StartNew<int>(() => { return Calc(1000); }).ContinueWith(ts => { for (int i = 0; i < 1000; i++) { System.Threading.Thread.Sleep(10); countValue += i; } return countValue + ts.Result; }); // Task.WaitAll(result); await result; sw.Stop(); this.richTextBox1.Text = "最終計算結果:" + result.Result + "異步方法耗時:" + (sw.ElapsedMilliseconds / 1000) + "秒"; } /// <summary> /// 委托的異步調用,界面不能點擊,程序執行時間10S /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private async void button2_Click(object sender, EventArgs e) { Stopwatch sw = new Stopwatch(); sw.Start(); Func<int, int> Func = Calc; IAsyncResult AsyncResult = Func.BeginInvoke(1000, null, null); int finialValue = 0; int countValue = 0; Func<int> Func2 = (() => { for (int i = 0; i < 1000; i++) { System.Threading.Thread.Sleep(10); countValue += i; } return countValue; }); IAsyncResult AsyncResult2 = Func2.BeginInvoke(null, null); int value1 = Func.EndInvoke(AsyncResult); int value2 = Func2.EndInvoke(AsyncResult2); finialValue = value1 + value2; sw.Stop(); this.richTextBox1.Text = "最終計算結果:" + finialValue + "BeginInvoke異步方法耗時:" + (sw.ElapsedMilliseconds / 1000) + "秒"; } } }

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 WindowsFormsApplication1 { public partial class frmBackgroundworker : Form { BackgroundWorker bgWorker = new BackgroundWorker(); public frmBackgroundworker() { InitializeComponent(); bgWorker.WorkerReportsProgress = true; bgWorker.WorkerSupportsCancellation = true; bgWorker.DoWork += bgWorker_DoWork; bgWorker.RunWorkerCompleted += bgWorker_RunWorkerCompleted; bgWorker.ProgressChanged += bgWorker_ProgressChanged; } void bgWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Cancelled) { this.lblInfo.Text = "用戶已取消"; return; } if (e.Error != null) { this.lblInfo.Text = e.Error.Message; return; } this.lblInfo.Text = e.Result.ToString(); } void bgWorker_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker bw = sender as BackgroundWorker; for (int i = 1; i <= 100; i++) { if (bw.CancellationPending) { e.Cancel = true; return; } System.Threading.Thread.Sleep(20); bw.ReportProgress(i, string.Format("當前完成進度{0}%", i)); } System.Threading.Thread.Sleep(1000); e.Result = "執行完成"; } void bgWorker_ProgressChanged(object sender, ProgressChangedEventArgs e) { this.progressBar1.Value = e.ProgressPercentage; this.lblInfo.Text = e.UserState.ToString(); } private void btn_Start_Click(object sender, EventArgs e) { try { bgWorker.RunWorkerAsync(); } catch (Exception ex) { } } private void btn_Cancel_Click(object sender, EventArgs e) { try { bgWorker.CancelAsync(); } catch (Exception) { throw; } } } }