[.net 面向對象程序設計進階] (19) 異步(Asynchronous) 使用異步建立快速響應和可伸縮性的應用程序
html
本節導讀:前端
本節主要說明使用異步進行程序設計的優缺點及如何經過異步編程.ajax
使用傳統方法BeginInvoke / EndInvoke來實現異步。編程
使用async/await 建立異步方法和事件。多線程
經過異步編程建立具備快速響應和可伸縮性的應用程序。 異步
讀前必備:async
A.委託 [.net 面向對象編程基礎] (21) 委託異步編程
B.事件 [.net 面向對象編程基礎] (22) 事件函數
1.異步程序設計的優缺點:測試
A.讓用戶界面快速響應;對於耗時操做阻塞UI線程,經過異步回調可以使用UI快速響應。
B.建立高伸縮性的應用。對於服務端應用,建立更多線程來處理消耗資源較多,使用異步可以使用主線程繼續工做,不須要等待返回。使用程序具備更好的伸縮性。
對於異步的缺點,最主要一點就是比建立同步程序難度大一些,首先使用傳統的方法建立異步,比起同步更容易出錯。不過隨着.NET的不斷髮展和第三方異步組件的豐富,建立異步應用程序也變得愈來愈簡單了。
2.異步的實現
對於.NET中的異步編程,.NET在各個方向都幾乎提供了同步和異步的兩個方式來實現,在這裏咱們不能把.NET中所有的異步編程方法都列舉出來了,下面介紹幾種經常使用且實用的異步方法。
3.使用BeginInvoke / EndInvoke實現異步
3.1 簡單的異步示例
下面看一個簡單的示例:
//使用一個有返回值的泛型委託來執行BeginInvoke Func<string> myFunc = new Func<string>(()=>{ Thread.Sleep(10); return "我是異步執行完成的返回值 當前時間:" + System.DateTime.Now.ToString(); }); IAsyncResult asynResult = myFunc.BeginInvoke(null, null); //在異步沒有完成前,能夠作別的事 while (!asynResult.IsCompleted) { //當不是true時,就執行這裏的代碼 Console.WriteLine("當前異步是否完成:" + asynResult.IsCompleted + " 當前時間:" + System.DateTime.Now.ToString()); } string result = myFunc.EndInvoke(asynResult);//當是true時,就將結果返回顯示 Console.WriteLine(result);
運行結果以下:
在異步沒有完成時,能夠繼續工做作一些想作的事,異步完成後返回結果。
3.2 使用異步的超時 WaitOne 判斷異步完成
除了上面使用IsCompleted來判斷異步完成以外,也能夠使用超時來判斷異步的完成狀況
示例以下 :
//使用一個有返回值的泛型委託來執行BeginInvoke Func<string> myFunc = new Func<string>(()=>{ int i = 0; while (i<99999999) ++i; return "異步執行完成的返回值" + (i).ToString() + " 當前時間:" + System.DateTime.Now.ToString(); }); IAsyncResult asynResult = myFunc.BeginInvoke(null, null); while (!asynResult.AsyncWaitHandle.WaitOne(10, false)) Console.Write("*"); string result = myFunc.EndInvoke(asynResult); Console.Write("\n"); Console.WriteLine(result);
運行結果以下:
3.3 回調
畢竟上述兩種等待不是一個好的方法。咱們在前端開發中使用過ajax的同窗確定知道,前端中異步使用一個回調函數在異步完成後完成咱們想要作的事,.NET天然也有相似的回調方法,
看示例:
//使用一個有返回值的泛型委託來執行BeginInvoke Func<string> myFunc = new Func<string>(()=>{ int i = 0; while (i<99999999) ++i; return "異步執行完成的返回值" + (i).ToString() + " 當前時間:" + System.DateTime.Now.ToString(); }); IAsyncResult asynResult = myFunc.BeginInvoke((result) => { string rst = myFunc.EndInvoke(result); Console.WriteLine("異步完成了,我該返回結果了!"); Console.WriteLine(rst); }, null);
運行結果以下 :
3.4 其它組件中的Begin\End異步方法
除了BeginInvoke / EndInvoke以外,.NET在不少類中提供了異步的方法,
如System.Net.HttpWebRequest類的BeginGetResponse和EndGetResponse方法,
這裏再也不一一列舉了,使用方法和上面的示例相似。
4. async/await
.NET 5.0 之後,讓異步編程變得更加簡單了,咱們介紹一下async和await。
它讓咱們編寫異步程序變得和同步同樣簡單,不但減小了代碼量,並且不會由於異步讓咱們程序邏輯被打亂。
4.1 異步方法
下面使用async 和 await關鍵字來建立一個異步方法,
在第一個方法裏調用第二個異步方法,
第二個異步方法中使用了多線程。
聽起來很繞口,不過整個代碼編寫和同步方法沒有什麼區別,只是多一個關鍵字。
static void Main(string[] args) { Console.WriteLine("主線程開始.."); AsyncMethod(); Thread.Sleep(1000); Console.WriteLine("主線程結束.."); Console.ReadKey(); } static async void AsyncMethod() { Console.WriteLine("開始異步方法"); var result = await MyMethod(); Console.WriteLine("異步方法結束"); } static async Task<int> MyMethod() { for (int i = 0; i < 5; i++) { Console.WriteLine("異步執行" + i.ToString() + ".."); await Task.Delay(1000); //模擬耗時操做 } return 0; }
運行結果以下:
4.2 異步事件
下面使用一個WinForm應用程序來測試一下異步事件,咱們建立一個同步的Click事件和一個異步的Click事件,先觸發異步,而後緊接着觸發同步,看一下運行結果。
//同步事件 private void button2_Click(object sender, EventArgs e) { textBox1.Text += "同步執行開始..\r\n"; MyMethodFirst(); textBox1.Text += "同步執行結束..\r\n"; } //同事事件調用方法 int MyMethodFirst() { for (int i = 0; i < 5; i++) { textBox1.Text += "同步執行" + i.ToString() + "..\r\n"; } return 0; } //異步事件 private async void button3_Click(object sender, EventArgs e) { textBox1.Text += "異步執行開始..====\r\n"; await MyMethodSencond(); textBox1.Text += "異步執行結束..====\r\n"; } //異步事件調用方法 async Task<int> MyMethodSencond() { for (int i = 0; i < 5; i++) { textBox1.Text += "異步執行" + i.ToString() +" ..====\r\n"; await Task.Delay(1000); //模擬耗時操做 } return 0; }
運行結果以下:
5. 本節要點
A.使用傳統方法BeginInvoke / EndInvoke來實現異步
B.使用async/await 建立異步方法和事件
==============================================================================================
<若是對你有幫助,記得點一下推薦哦,若有有不明白或錯誤之處,請多交流>
<對本系列文章閱讀有困難的朋友,請先看《.net 面向對象編程基礎》>
<轉載聲明:技術須要共享精神,歡迎轉載本博客中的文章,但請註明版權及URL>
==============================================================================================