使用委托可以执行的一项有用操作是实现回调。回调是传入函数的方法,在函数结束执行时调用该方法。
例如,有一个执行一系列数学操作的函数。在调用该函数时,也向其传递一个回调方法,从而在函数完成其计算工作时,调用回调方法,向用户通知计算结果。
同步回调
首先声明两个方法:
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变量。
在使用异步回调时,可以通过在不同的线程中执行程序的不同部分来使程序更快速的响应。