C#中的委托和事件学习(续)

2019-05-12 07:23:05王冬梅

此时的输出为:


Client application started!

Method invoked!
Main Thread: Client executed 1 second(s).
Pool Thread: Add executed 1 second(s).
Main Thread: Client executed 2 second(s).
Pool Thread: Add executed 2 second(s).
Method complete!
Main Thread: Client executed 3 second(s).
Result: 7


Press any key to exit...

现在执行完这段代码只需要3秒钟时间,两个for循环所产生的输出交替进行,这也说明了这两段代码并行执行的情况。可以看到Add()方法是由线程池中的线程在执行,因为Thread.CurrentThread.IsThreadPoolThread返回了True,同时我们对该线程命名为了Pool Thread。另外我们可以看到通过EndInvoke()方法得到了返回值。

有时候,我们可能会将获得返回值的操作放到另一段代码或者客户端去执行,而不是向上面那样直接写在BeginInvoke()的后面。比如说我们在Program中新建一个方法GetReturn(),此时可以通过AsyncResult的AsyncDelegate获得del委托对象,然后再在其上调用EndInvoke()方法,这也说明了AsyncResult可以唯一的获取到与它相关的调用了的方法(或者也可以理解成委托对象)。所以上面获取返回值的代码也可以改写成这样:

static int GetReturn(IAsyncResult asyncResult) {
   AsyncResult result = (AsyncResult)asyncResult;
   AddDelegate del = (AddDelegate)result.AsyncDelegate;
   int rtn = del.EndInvoke(asyncResult);
   return rtn;
 }

然后再将int rtn = del.EndInvoke(asyncResult);语句改为int rtn = GetReturn(asyncResult);。注意上面IAsyncResult要转换为实际的类型AsyncResult才能访问AsyncDelegate属性,因为它没有包含在IAsyncResult接口的定义中。

BeginInvoke的另外两个参数分别是AsyncCallback和Object类型,其中AsyncCallback是一个委托类型,它用于方法的回调,即是说当异步方法执行完毕时自动进行调用的方法。它的定义为:

public delegate void AsyncCallback(IAsyncResult ar);

Object类型用于传递任何你想要的数值,它可以通过IAsyncResult的AsyncState属性获得。下面我们将获取方法返回值、打印返回值的操作放到了OnAddComplete()回调方法中:

public delegate int AddDelegate(int x, int y);

class Program9 {

   static void Main(string[] args) {

     Console.WriteLine("Client application started!n");
     Thread.CurrentThread.Name = "Main Thread";

     Calculator cal = new Calculator();
     AddDelegate del = new AddDelegate(cal.Add);
     string data = "Any data you want to pass.";
     AsyncCallback callBack = new AsyncCallback(OnAddComplete);
     del.BeginInvoke(2, 5, callBack, data);   // 异步调用方法

    // 做某些其它的事情,模拟需要执行3秒钟
    for (int i = 1; i <= 3; i++) {
       Thread.Sleep(TimeSpan.FromSeconds(i));
       Console.WriteLine("{0}: Client executed {1} second(s).",
         Thread.CurrentThread.Name, i);
     }

     Console.WriteLine("nPress any key to exit...");
     Console.ReadKey();
   }

   static void OnAddComplete(IAsyncResult asyncResult) {
     AsyncResult result = (AsyncResult)asyncResult;
     AddDelegate del = (AddDelegate)result.AsyncDelegate;
     string data = (string)asyncResult.AsyncState;

     int rtn = del.EndInvoke(asyncResult);
     Console.WriteLine("{0}: Result, {1}; Data: {2}n", 
       Thread.CurrentThread.Name, rtn, data);
   }
 }
public class Calculator { /* 与上面同,略 */}