等待异步委托的几种方式,觉得这个比较重要的,如是学习了下,把学习笔记记录如下 (一)代码: using System; using System.Collections.Generic; using System.Linq; using System.Text; //添加命名空间 using System.Threading; using System.Diagnostics; namespace 线程和同步 { //创建线程方式: //(一)异步委托创建线程 // 等待异步委托的方式: // (1)投票 // (2)等待句柄 // (3)异步回调 //(二)Thread类创建线程 class Program { public delegate int TakesAWhileDelegate(int data, int ms); static int TakesAWhile(int data, int ms) { Console.WriteLine("TakesAWhile started"); Thread.Sleep(ms); Console.WriteLine("TakesAWhile completed"); return ++data; } static void Main(string[] args) { //Test1(); //Test2(); Test3(); Console.ReadKey(); } //投票:是一种技术,检查委托是否完成了任务。 static void Test1() { TakesAWhileDelegate d1 = TakesAWhile;//定义异步委托实例 //Delegate类提供了方法BeginInvoke //(1)BeginInvoke总含有AsyncCallBack和Object类型的额外参数,BeginInvoke(paramer1,paramer2,..,AsyncCallBack,Object) //(2)返回类型为IAsyncResult.可获得的信息,并验证委托是否完成了任务(IsCompleted) IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null); //只要委托没有完成其任务,程序的主线程就继续执行While循环。 while (!ar.IsCompleted) { //在主线程中做些其他的事情 Console.Write("."); Thread.Sleep(50); } int result = d1.EndInvoke(ar);//EndInvoke()方法带回返回值。 Console.WriteLine("result:{0}",result); //现象: //可以看到主线程和委托线程同时运行,在委托线程执行完毕后,主线程就停止循环。 } //等待句柄:使用IAsyncWaitHandle属性等待句柄,这个属性返回一个WaitHandle类型的对象 static void Test2() { TakesAWhileDelegate d1 = TakesAWhile; IAsyncResult ar = d1.BeginInvoke(1, 3000, null, null); while(true) { Console.Write("."); //WaitHandle,它可以等待委托线程完成其任务 //WaitOne()将一个超时时间作为可选的第一个参数,在其中可以定义要等待的最大时间,这里设置为50毫秒, //如果发生超时,WaiteOne()就返回false,While循环会继续执行,如果等待操作成功,就用一个中断退出while循环 if (ar.AsyncWaitHandle.WaitOne(50, false)) { Console.WriteLine("Can get the result now"); break; } } int result = d1.EndInvoke(ar);//EndInvoke()方法带回返回值。 Console.WriteLine("result:{0}", result); } //异步回调 //注意:使用回调方法,必须注意这个方法在线程中调用,而不是在主线程中调用 static void Test3() { TakesAWhileDelegate d1 = TakesAWhile; //BeginInvoke总含有AsyncCallBack //TakeAWhileCompleted赋予第三个参数以满足AsyncCallBack委托需求,对于最后一个参数可以传递任意对象,以便从回调方法中访问它 //这样回调方法就可以使用他获取异步方法的结果 //只要TakesAWhileDelegate,完成了其任务,就调用TakeAWhileCompleted方法,不需要在主线程中等待结果 //但是在委托线程饿任务未完成之前,不能停止主线程,除非刚刚停止的委托线程没有问题 d1.BeginInvoke(1, 3000,TakeAWhileCompleted ,d1); for (int i = 0; i < 100; i++) { Console.Write("."); Thread.Sleep(50); } } //AsyncCallback委托定义了一个IAsyncResult的参数,其返回值是void static void TakeAWhileCompleted(IAsyncResult ar) { if (ar == null) throw new ArgumentNullException("ar"); TakesAWhileDelegate d = ar.AsyncState as TakesAWhileDelegate; Trace.Assert(d != null, "Invalid object type"); int result = d.EndInvoke(ar);//EndInvoke()方法带回返回值。 Console.WriteLine("result:{0}", result); } //异步回调(lamda表达式写法) //运用场景: //只有当代码不多,且实现代码不需要用于不同地方时,才应使用lamda表达式 static void Test4() { TakesAWhileDelegate d1 = TakesAWhile; d1.BeginInvoke(1,3000, ar=>//ar参数是IAsyncResult类型,在执行代码中,不需要把一个值赋给BeginInvoke()方法的最后一个参数, //因为lamda表达式可以直接访问该方法的尾部的变量dl,但是lamda表达式仍是在委托线程中调用的 { int result = d1.EndInvoke(ar); Console.WriteLine("result:{0}", result); }, null); for (int i = 0; i < 100; i++) { Console.Write("."); Thread.Sleep(50); } } } } 运行截图: (1)Test1运行截图 (2)Test2运行截图 (3)Test3运行截图