一.如何理解异步编程

使用 .NET 异步编程,在程序继续执行的同时对 .NET 类方法进行调用,直到进行指定的回调为止;

如果没有提供回调,则直到对调用的阻塞、轮询或等待完成为止。

例如,一个程序可以调用一个方法,该方法枚举一个较大的列表,同时主程序将继续执行。在完成枚举后,进行回调并由程序对它进行寻址。

二.使用异步编程的领域

文件IO 流IO 套接字IO

远程处理信道(HTTP、TCP)和代理

使用 ASP.NET 创建的 XML Web services

ASP.NET Web 窗体

使用 MessageQueue 类的消息队列

异步委托

三.如何进行进行异步调用?

.NET Framework 允许异步调用任何方法。

定义需要调用的方法具有相同签名的委托

公共语言运行库将自动为该委托定义具有适当签名的 BeginInvoke 和 EndInvoke 方法。

四.委托与传统的函数指针的区别

委托是安全的面向对象的函数指针,为了加深学员对此的理解,分别用C++实现一个函数指针和C#实现一个委托,见例1和例2.

五.Delegate类、MulticastDelegate和delegate关键字介绍

为了加深学员的理解,使用ILDASM反汇编工具查看例2生成的DLL的IL代码

重点是Invoke、BeginInvoke 和 EndInvoke方法以及参数的含义

六.IAsyncResult接口

IAsyncResult 接口用于监视和管理异步操作。该接口是从开始操作返回的并被传递到结束操作,以将开始操作和结束操作相关联。如果回调被

指定为开始操作的一部分,则 AsyncResult 被传递到回调。它的四个属性如下:

AsyncState :返回在开始操作方法调用中作为最后一个参数提供的对象。

AsyncWaitHandle :返回 WaitHandle,后者可用于执行 WaitHandle.WaitOne、WaitAny 或 WaitAll。

CompletedSynchronously :如果开始操作调用已同步完成,则 CompletedSynchronously 属性将被设置为 true。

IsCompleted :在服务器已处理完调用后,IsCompleted 属性将被设置为 true。

七.四种异步编程方法

调用BeginInvoke后,有四种选择:

(1)进行某些操作,然后调用 EndInvoke 一直阻塞到调用完成。 (见例3)

(2)使用 IAsyncResult.AsyncWaitHandle 获取 WaitHandle,使用它的     WaitOne 方法将执行一直阻塞到发出 WaitHandle 信号,然后

调用 EndInvoke。(见例4)

(3)轮询由 BeginInvoke 返回的 IAsyncResult,确定异步调用何时完成,然后调用 EndInvoke。(见例5)

(4)将用于回调方法的委托传递给 BeginInvoke。该方法在异步调用完成后在 ThreadPool 线程上执行,它可以调用 EndInvoke。(见例6

注意:始终在异步调用完成后调用 EndInvoke。

八.Webservice异步调用、远程对象异步调用、异步Socket的实现,代码取自MSDN

九.代码部分

例(1)

////////////////////////////////////////

#include <iostream.h>

typedef int CFun(int);

void FunTest(CFun * f,int i)

{

 cout<<f(i)<<endl;

}

int Fun1(int i)

{

 return i;

}

int Fun2(int i,int j)

{

 return i+j;

}

int main()

 FunTest((CFun *)Fun1,5);

 FunTest((CFun *)Fun2,3);//可以通过编译,运行时产生不可预知的结果

 return 0;

}

///////////////////////////////////////

例(2)

///////////////////////////////////////

using System;

namespace DelegateTest

{

 public delegate int MyDelegate1(int i);

 public delegate int MyDelegate2(int i,int j);

 public delegate int MyDelegate3(int i,int j,int k);

 class ClassMain

 {

  [STAThread]

  static void Main(string[] args)

  {

   ClassMain cm=new ClassMain();

   MyDelegate1 md1=new MyDelegate1(cm.Fun1);

   int n=md1(10);

   Console.WriteLine(n);

   MyDelegate2 md2=new MyDelegate2(cm.Fun2);

   n=md2(10,100);

   Console.WriteLine(n);

   //错误的代码,委托和函数签名不匹配,不能通过编译

   //md=new MyDelegate(cm.Fun2);

  }

  private int Fun1(int i)

  {

   return i;

  }

  private int Fun2(int i,int j)

  {

   return i+j;

  }

 }

}

///////////////////////////////////////

例(3)

///////////////////////////////////////

using System;

using System.Threading;

namespace AsyTest1

{

 public delegate void MyDelegate();

 class ClassMain

 {

  [STAThread]

  static void Main(string[] args)

  {

   MyDelegate md=new MyDelegate(Fun);

   IAsyncResult ar=md.BeginInvoke(null,null);

   int i=1;

   //调用线程模拟正在做一些操作

   while(i<1000000000)

   {

    i+=2;

    i-=1;

   }

   Console.WriteLine("调用线程的工作做完了,下面等待异步调用完成");

   md.EndInvoke(ar);

   Console.WriteLine("程序结束");

  }

  static void Fun()

  {

   //模拟正在进行一些耗时操作,比如检索文件

   Thread.Sleep(10000);

   Console.WriteLine("Fun执行完毕");

  }

 }

}

//////////////////////////////////////

例(4)

//////////////////////////////////////

using System;

using System.Threading;

namespace AsyTest2

{

 public delegate int MyDelegate(int i,int j);

 class ClassMain

 {

  [STAThread]

  static void Main(string[] args)

  {

   MyDelegate md=new MyDelegate(Fun);

   IAsyncResult ar=md.BeginInvoke(10,20,null,null);

   //使用等待句柄

   ar.AsyncWaitHandle.WaitOne();

   Console.WriteLine("等待结束");

   int k=md.EndInvoke(ar);

   Console.WriteLine("程序结束,k={0}",k);

  }

  static int Fun(int i,int j)

  {

   //模拟正在进行一些耗时操作,比如检索文件

   Thread.Sleep(10000);

   Console.WriteLine("Fun执行完毕");

   return i+j;

  }

 }

}

//////////////////////////////////////

例(5)

//////////////////////////////////////

using System;

using System.Threading;

namespace AsyTest3

{

 public delegate int MyDelegate(int i,int j);

 class ClassMain

 {

  [STAThread]

  static void Main(string[] args)

  {

   MyDelegate md=new MyDelegate(Fun);

   IAsyncResult ar=md.BeginInvoke(10,20,null,null);

   while(ar.IsCompleted==false)

   {

    //模拟正在做一些其他操作

    Console.WriteLine(".....");

    Thread.Sleep(2000);

   }

   Console.WriteLine("轮询结束");

   int k=md.EndInvoke(ar);

   Console.WriteLine("程序结束,k={0}",k);

  }

  static int Fun(int i,int j)

  {

   //模拟正在进行一些耗时操作,比如检索文件

   Thread.Sleep(10000);

   Console.WriteLine("Fun执行完毕");

   return i+j;

  }

 }

}

//////////////////////////////////////

例(6)

//////////////////////////////////////

using System;

using System.Threading;

namespace AsyTest4

{

 public delegate int MyDelegate(int i,int j);

 class ClassMain

 {

  [STAThread]

  static void Main(string[] args)

  {

   MyDelegate md=new MyDelegate(Fun);

   //启动异步调用,指定回调函数CallBack

   IAsyncResult ar=md.BeginInvoke(10,20,new AsyncCallback(CallBack),md);

   //主函数继续执行其他操作

   Thread.Sleep(5000);

   Console.WriteLine("主函数的操作完成");

   //避免主函数在Fun之前结束

   Console.ReadLine();

  }

  static int Fun(int i,int j)

  {

   //模拟正在进行一些耗时操作,比如检索文件

   Thread.Sleep(10000);

   return i+j;

  }

  static void CallBack(IAsyncResult ar)

  {

   //获取主函数中的md对象引用

   MyDelegate md=(MyDelegate)ar.AsyncState;

   int k=md.EndInvoke(ar);

   Console.WriteLine("Fun执行完毕,回调函数执行,结果={0}",k);

  }

 }