使用委託實現同步回撥與非同步回撥
使用委託可以執行的一項有用操作是實現回撥。回撥是傳入函式的方法,在函式結束執行時呼叫該方法。
例如,有一個執行一系列數學操作的函式。在呼叫該函式時,也向其傳遞一個回撥方法,從而在函式完成其計算工作時,呼叫回撥方法,向用戶通知計算結果。
同步回撥
首先宣告兩個方法:
AddTwoNumbers():接受兩個整型實參以及一個型別委託
ResultCallback():接受一個字串,並顯示出來。程式碼如下:
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace DelegateCallBack { class Program { delegate void CallbackDelegate(string msg); static void Main(string[] args) { //方式一: CallbackDelegate result = ResultCallback; AddTwoNumbers(5, 3, result); //方式二: AddTwoNumbers(5, 3, ResultCallback); Console.Read(); } static private void AddTwoNumbers(int num1,int num2,CallbackDelegate callback) { int result = num1 + num2; callback(result.ToString()); } static private void ResultCallback(string msg) { Console.WriteLine(msg); } } }
非同步回撥
回撥在非同步情況下最有用。前面例項中說明的回撥是同步回撥,也就是按順序呼叫函式。如果AddTwoNumbers方法花費較長時間來執行,則該函式之後的所有的語句將被阻塞。 組織較好的方式是非同步呼叫AddTwoNumbers方法。非同步呼叫函式允許主程式繼續執行,而不需要等待該函式返回。 在這種非同步模型中,當呼叫AddTwoNumbers函式時,在其後的語句繼續執行。當函式結束時,他呼叫ResultCallback函式。
下面使用非同步回撥重寫前面的程式:
using System; using System.Collections.Generic; using System.Linq; using System.Runtime.Remoting.Messaging; using System.Text; using System.Threading.Tasks; namespace DelegateCallBack { class Program { delegate int MethodDelegate(int num1, int num2); static void Main(string[] args) { MethodDelegate result = AddTwoNumbers; //引用非同步操作完成時呼叫的方法 AsyncCallback callback = new AsyncCallback(ResultCallback); Console.WriteLine("開始非同步呼叫"); IAsyncResult iresult = result.BeginInvoke(5, 3, callback, null); Console.WriteLine("主程式繼續執行"); Console.Read(); } static private int AddTwoNumbers(int num1,int num2) { int result = num1 + num2; System.Threading.Thread.Sleep(5000); return result; } static private void ResultCallback(IAsyncResult ar) { MethodDelegate dele = (MethodDelegate)((AsyncResult)ar).AsyncDelegate; int result = dele.EndInvoke(ar); Console.WriteLine("result={0}",result); } } }
程式一執行:
五秒後
現在我們分析下程式,首先我們定義一個委託型別,從而可以指向AddTwoNumbers方法。
接下來,定義一個型別為AsyncCallback的委託。AsyncCallback是引用某個方法的委託,當非同步操作完成時呼叫該方法。
使用result 委託的BeginInvoke()方法非同步呼叫AddTwoNumbers(),並且向該方法傳遞兩個整型以及在該方法結束執行時回撥的委託。
BeginInvoke()方法非同步呼叫委託,在呼叫非同步委託之後,下一條語句會繼續執行。該方法返回型別為IAsyncResult 的變數,該變量表示非同步操作的狀態。
在ResultCallback方法中,首先使用AsyncDelegate特性獲得指向AddTwoNumbers()方法的委託,該特性返回進行非同步呼叫的委託。接下來,使用EndInvoke()方法會的非同步呼叫的結果,向該方法傳遞IAsycResult變數。
在使用非同步回撥時,可以通過在不同的執行緒中執行程式的不同部分來使程式更快速的響應。