异步调用WEBSERVICE
Web 服务描述语言工具 (Wsdl.exe) 生成客户端代理类来访问指定的 Web 服务时,会为该代理类提供与每个 Web 服务方法进行异步通信的两种机制。第一种机制是 Begin/End 模式。第二种机制是在 .NET Framework 2.0 版中提供的事件驱动的异步编程模式。
Begin/End 调用模式
Wsdl.exe 为 Web 服务中发布的每项操作自动创建三个方法(ASP.NET 中的 Web 服务方法)。一个方法针对同步访问;另外两个方法针对异步访问。即使该 Web 服务方法只有一个同步实现也不例外。下表对这三个方法进行了说明:
代理类中方法的名称 |
说明 |
<NameOfWebServiceMethod> |
为名为 <NameOfWebServiceMethod> 的 Web 服务方法同步发送消息。 |
Begin<NameOfWebServiceMethod> |
开始与名为 <NameOfWebServiceMethod> 的 Web 服务方法的异步消息通信。客户端指示 Begin 方法开始对服务调用进行处理,但立即返回。返回值不是 Web 服务方法指定的数据类型,而是实现 IAsyncResult 接口的类型。 |
End <NameOfWebServiceMethod> |
结束与名为 <NameOfWebServiceMethod> 的 Web 服务方法的异步消息通信,返回的值是 Web 服务方法调用的结果。 |
Begin 和 End 方法均遵循 .NET Framework 异步设计模式的命名约定。该设计模式规定每种同步方法有两种如此命名的异步方法。
使用 Begin/End 模式实现进行异步方法调用的 Web 服务客户端
客户端如何知道何时调用 End 方法呢?根据 .NET Framework 的定义,有两种方法可以使客户端确定这一点:
· 等待方法:使用 WaitHandle 类的方法之一使客户端等待方法完成。
· 回调方法:向 Begin 方法传递一个回调函数,在该方法完成处理后再调用该函数来检索结果。
注意:无论客户端选择两种方法中的哪一种与 Web 服务进行异步通信,收发的 SOAP 消息都与通过同步代理方法生成的 SOAP 消息相同。也就是说,仍然只有一个 SOAP 请求和 SOAP 响应通过网络发送和接收。代理类通过使用与客户端调用 Begin 方法时使用的线程不同的线程来处理 SOAP 响应,从而实现该目的。因此,在代理类接收和处理 SOAP 响应时,客户端可以在其线程上继续执行其他工作。
使用 Begin/End 模式的等待方法
WaitHandle 类实现下列支持等待同步对象得到信号通知的方法:WaitOne、WaitAny 和 WaitAll。当同步对象得到信号通知时,表示等待指定资源的线程此时可以访问该资源了。Web 服务客户端通过 Begin 方法返回的 IAsyncResult 对象的 AsyncWaitHandle 属性,来访问 WaitHandle 对象。
具体做法:
1、 Web 服务客户端调用所生成的代理类的 Begin 方法。
IAsyncResult ar = pf.BeginFactorize(factorizableNum, null, null);
2、 Web 服务客户端通过返回的 IAsyncResult 的 AsyncWaitHandle 属性来访问 WaitHandle 对象。
ar.AsyncWaitHandle.WaitOne()
3、 等待方法返回后,客户端调用 End 方法来获取结果。
results = pf.EndFactorize(ar);
使用 Begin/End 模式的回调方法
具体做法:
- 定义实现 AsyncCallback 委托的回调函数。
public static void FactorizeCallback(IAsyncResult ar)
- 实例化 AsyncCallback 委托。
AsyncCallback cb = new AsyncCallback(TestCallback.FactorizeCallback);
- 调用 Begin 方法,将回调函数作为第二个参数传递,将提供状态的对象(在本示例中是 PrimeFactorizer 的客户端实现)作为第三个参数传递。
IAsyncResult ar = pf.BeginFactorize(factorizableNum, cb, pf);
- 在 Begin 方法返回的 IAsyncResult 上检查 IsCompleted 属性。如果客户端已收到服务器的响应,该值将设置为 true。