如果委托对象的调用列表中只有一个方法(引用方法),就可以异步执行这个方法,通过调用委托类特有的两个方法BeginInvoke和EndInvoke去执行。

异步编程中的BeginInvoke和EndInvoke_回调方法

BeginInvoke和EndInvoke 的三种模式:

异步编程中的BeginInvoke和EndInvoke_异步方法_02

BeginInvoke方法的参数列表:

  1.引用方法所需要的参数;

  2.两个额外的参数,callback参数和state参数;

  BeginInvoke方法返回一个IAsyncResult接口类型对象,这个接口引用包含了在线程池中运行的异步方法的状态。

异步编程中的BeginInvoke和EndInvoke_ide_03

 

EndInvoke方法:

               EndInvoke方法,用来获取异步方法执行时,异步方法的返回值,并释放线程的资源,当EndInvoke被调用时,如果线程池的线程仍在执行,调用线程会停止,并等待,直到异步线程执行完,被清理并返回值。EndInvoke方法的参数列表中有一个是IAsyncResult 类型,即主线程调用BeginInvoke时返回的IAsyncResult接口对象,还有可能是Ref或Out类型参数。

特性:

异步编程中的BeginInvoke和EndInvoke_回调方法_04

 

EndInvoke参数还包括Ref和out参数 :    

异步编程中的BeginInvoke和EndInvoke_ide_05

 

等待一直完成模式 :



using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace waituntildone
{
delegate int MyDel(int x, int y);
class Program
{
static int sum(int x,int y) //异步方法
{
Console.WriteLine(" inside sum1");
Thread.Sleep(80);
Console.WriteLine(" inside sum2");
Thread.Sleep(8000);
return x+y;
}
static void Main(string[] args)
{
MyDel Del = new MyDel(sum);
IAsyncResult iar = Del.BeginInvoke(4,6,null,null); //开始异步执行
//Thread.Sleep(10);
Console.WriteLine("After BeginInvoke"); //程序在执行异步方法的同时,执行该语句
Console.WriteLine("Doing stuff");
int result = Del.EndInvoke(iar); //等待,直到异步方法执行完毕,将结果
Console.WriteLine("After EndInvoke result = {0}",result);
Console.ReadKey();
}
}
}


 

 

轮询模式: 

在轮询模式中,原始线程发起异步方法 调用后,然后通过检查 IAsnyResult接口对象的IsComplete属性,判断异步方法是否完   成,如果没完成主线程在等待过程中可以做其它事情,EndInvoke方法与一直等待完成模式一样必须等待异步方法完成之后才     执行。轮询模式与等待一直完成模式相比,只增加了一步:通过检查 IAsnyResult接口对象的IsComplete属性的判断异步方法     是否完成,如没完成在检查过程中可以做其它事情。




using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
//轮询模式与等待一直完成模式相比只增加了iar.IsCompleted判断是否完成的步骤
namespace polling_
{
class Program
{
delegate int MyDel(int x,int y);
static int sum(int x, int y)
{
Console.WriteLine(" insid sum");
Thread.Sleep(1000);
return x + y;
}
static void Main(string[] args)
{
MyDel Del = new MyDel(sum);
IAsyncResult iar = Del.BeginInvoke(5,6,null,null); //发起异步调用
Console.WriteLine("After BeginInvoke");
while (!iar.IsCompleted) //检测IAsyncResult接口的IsCompleted属性判断异步方法是否完成
{
Console.WriteLine("Sum Not Complete");
for (int i = 0; i < 100000; i++)
{
for (int j = 0; j < 1000; j++)
{

}
}
}
Console.WriteLine("Sum Completed !!!");
//Thread.Sleep(3000);

int result = Del.EndInvoke(iar); //异步方法执行完后才会执行这一句
Console.WriteLine("Result: {0}",result);
Console.ReadKey();
}
}
}


 

回调模式:

回调模式的不同之处在于,一旦主线程线程发起了异步方法,它就自己管自己了,不再考虑异步方法是否执行完成,当异步方法执行完后,系统会通过调用一个回调方法处理异步方法的结果,和调用委托的EndInvoke方法。

     回调方法:

     回调方法的返回类型为void,以一个IAsyncResult接口类型的参数做为形参:

异步编程中的BeginInvoke和EndInvoke_回调方法_06

AsyncResult类:

                当调用委托的BeginInvoke方法时,系统会创建一个AsyncResult类对象,  BeginInvoke方法执行完后,方法返回属于AsyncResult类对象中的一个IAsyncResult接口类型的引用。

异步编程中的BeginInvoke和EndInvoke_主线程_07

 

BeginInvoke方法的参数意义:             

                              IAsyncResult   BeginInvoke(-------,AsyncCallback callback,object state) 

   第一个参数callback,回调方法的名字

   第二个参数state可以为null,或发送给回调函数的参数的对象,参数类型是object,在回调函数中必须转换成正确的类型。

   回调方法和BeginInvoke方法是通过BeginInvoke方法内部的 最后两个参数关联的                     

   两种方法为BeginInvoke方法第一个参数赋值:

    1.使用回调方法创建AsyncCallback 类型的委托 

    2.只提供回调方法的名称,编译器会自动创建委托


异步编程中的BeginInvoke和EndInvoke_ide_08

 

回调模式是在回调方法内部,通过调用委托的EndInvoke方法来处理异步方法返回的结果,释放线程所占用的资源,而等待直到完成模式和轮询模式是在主线程中调用的;

要调用委托的EndInvoke方法,必须要有委托的引用,在回调方法内部,先是将回调方法的IAsyncResult接口类型通过里氏转换转换为AsyncResult类类型,然后再调用AsyncResult类的AsyncDelegate属性转化为合适的委托类型

 



using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace callback
{

delegate int Mydel(int x,int y);
class Program
{
static int sum(int x,int y) //异步方法
{
Console.WriteLine(" InSide Sum1");
Thread.Sleep(1000);
Console.WriteLine(" InSide Sum2");
return x + y;
}
//回调模式是在回调方法内部,通过调用委托的EndInvoke方法来处理异步方法返回的结果,释放线程所占用的资源而等待直到完成模式和轮询模式是在主线程中调用;
//要调用委托的EndInvoke方法,必须要有委托的引用,在回调方法内部,先是将回调方法的IAsyncResult接口类型通过里氏转换转换为AsyncResult类类型,
//然后再调用AsyncResult类的AsyncDelegate属性转化为合适的委托类型


static void callback_(IAsyncResult iar) //回调方法 无论如何回调方法中的内容必须在异步方法执行完后才执行
{
Console.WriteLine(" Inside CallWhenDone");
AsyncResult ar = (AsyncResult)iar; //里氏转换,如果父类中装的是子类的对象,那么可以将这个父类转换为子类对象
Mydel del = (Mydel)ar.AsyncDelegate; //通过AsyncResult类对象的AsyncDelegate属性转化为合适的Mydel委托类型
long result = del.EndInvoke(iar);
Console.WriteLine(" The result is: {0}",result);

}
static void Main(string[] args)
{
Mydel Del = new Mydel(sum);
Console.WriteLine("Before BeginInvoke");
IAsyncResult iar = Del.BeginInvoke(7,8,new AsyncCallback(callback_),Del); //Del焕成null结果也一样
Console.WriteLine("Doing more work in main");
Thread.Sleep(500);
Console.WriteLine("Done with Main.Exiting");
Console.ReadKey();
}
}
}