who am i ... i'm back.
分类: C/C++
2010-05-14 10:44:55
一.如何理解异步编程
使用 .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关键字介绍
重点是
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
typedef int CFun(int);
void FunTest(CFun * f,int i)
{
cout<
}
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);
}
}
--------------------------补充:如何通过asynccallback 获得 原始代理delegate ,进而获得 代理执行结果。
即通过IAsyncResult as AsyncResult 获取delegate 实例。
static void CallBackFunc(IAsyncResult ar)
{
AsyncResult result = ar as AsyncResult;
string inputMessage = result.AsyncState as string; //不通过.AsyncState 获取delegate
AsyncFuncDelegate caller = result.AsyncDelegate as AsyncFuncDelegate;
Console.WriteLine("invokde result: " + caller.EndInvoke(ar));
}