概述

在本篇随笔中,通过一些简单的示例来说一下Web Service中的异步调用模式。调用Web Service方法有两种方式,同步调用和异步调用。同步调用是程序继续执行前等候调用的完成,而异步调用在后台继续时,程序也继续执行,不必等待方法处理完成而直接返回。具体的调用流程见下图:

对于同步调用方法而言,UI线程依赖于方法的实现,方法执行时间过长将导致UI无法及时与用户进行交互。我们知道,在Windows客户端中,每个进程都有单一的UI进程,在服务器中,可扩展性依赖于线程的使用。对于异步调用方法而言,能够及时于用户交互响应,从而提供了良好的用户体验;同时也可以改善服务器的可扩展性,将服务器与通讯问题隔离。

客户端异步调用方法

在客户端异步调用是完全基于Proxy的方法,异步行为最简单的模式。Visual Studio和WSDL.EXE提供对它的直接支持。所以我们不必在Web服务应用程序中编写额外的代码来处理异步调用。

遍及.NET Framework的异步调用有一个基础的设计模式:Begin方法和End方法,他们分别用于开始和终止异步处理。Visual Studio和WSDL.exe生成了这两种方法:

Begin<WebServiceMethodName>——该方法通知Web服务开始处理调用,并立即返回。该方法不返回Web服务调用所指定的数据类型,而是返回一种实现IasyncResult接口的数据类型。

End<WebServiceMethodName>——该方法通知Web服务返回先前启动的Web方法所生成的结果。

IasyncResult接口包含了WaitHandle类型的AsyncWaitHandle特性。这个公共接口允许用户的客户应用程序等待调用,而且,该接口将用Any或All语义(例如WaitHandle.WaitOne,WaitAny和WaitAll)作为信号通知客户应用程序。例如,如果想要客户应用程序异步等候一个Web方法,可调用WaitOne来处理要完成的Web服务。

一般来说,客户端异步代理方法有两种实现机制:使用同步对象和回调机制(也许你可能对用这个词不习惯,实在找不到第二个词来代替,暂且这样称呼吧)

同步对象

同步对象允许用户对Web服务的方法进行调用(使用Begin方法),然后继续处理。在后面的程序中,可以调用End方法,传递同步对象,以便得到调用结果。这种方式下,能够继续执行函数中的程序流程,而不执行回调处理。在这里调用WaitOne()方法会挂起当前线程,避免忙等待的发生,直到Web Services方法调用结束返回后,该线程才会被重新唤起。

示例代码:

/// <summary>
/// 利用同步对象实现异步调用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_AsyncClient_Click(object sender, System.EventArgs e)
{
IAsyncResult ar = wsc.BeginHello(this.txt_UserName.Text, null, null); MessageBox.Show("Continue to do some other things"); ar.AsyncWaitHandle.WaitOne(); strHello = wsc.EndHello(ar); this.rtb_Result.Text = strHello;
}

回调机制

从本质上说,异步回调机制是委托的.NET等价物,它通过在异步操作完成时建立一个被调用的单独方法来进行工作。调用应用程序能够继续处理其他的任务,直到回调函数被调用为止。这就意味着处理已经完成了,应用程序可以正常运行了。使用同步对象不同于回调机制的区别是,当检查Web方法是否已经完成,以及检查Web方法中是否含有需要的结果时,我们无法对其进行控制,而在回调的情况中,Web方法一旦完成,这些工作就会被自动执行。

示例代码:

/// <summary>
/// 显示结果
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
public void UpdateResult(object sender, EventArgs e)
{
this.rtb_Result.Text = strHello;
} public void OnHelloComplete(IAsyncResult ar)
{
strHello = wsc.EndHello(ar); this.rtb_Result.Invoke(new EventHandler(UpdateResult));
} /// <summary>
/// 用回调机制实现异步调用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_CallBack_Click(object sender, System.EventArgs e)
{
AsyncCallback cb = new AsyncCallback(OnHelloComplete); wsc.BeginHello(this.txt_UserName.Text, cb, null);
}

使用回调机制还是同步对象取决于用户所面临的具体情况。在检查异步调用是否完成时,如果愿意对处理过程进行控制,那么可以选择使用同步对象。如果觉得自己编写代码来完成对Web服务的调用,且当方法一旦执行完毕就立即由所调用的特殊函数来处理所返回的结果更适合一些,那么就更适合用回调机制。

在客户端使用异步方法调用,可以改进UI响应度,在服务器端不需要实现异步操作,对服务器来说是透明的,而且客户端能够在任何时间选择阻塞。

服务端使用Soap One-Way方法

在服务器端使用One-Way方法实现异步调用,其实质是将单项消息发送到端点。这种方式的特点是方法没有返回值,客户端方法不会从调用的服务器端方法中收到返回值;我们无法判断方法结束的时间,对于结果需要显式通知或者轮询。

在Web 服务端,我们使用[SoapDocumentMethod]定义One-Way方法:

 [System.Web.Services.Protocols.SoapDocumentMethod(OneWay=true)]

示例代码:

/// <summary>
/// One-Way方式的异步调用Set
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_OneWay_Click(object sender, System.EventArgs e)
{
wsc.SetHello(this.txt_UserName.Text);
} /// <summary>
/// One-Way方式的异步调用Get
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btn_onewayGet_Click(object sender, System.EventArgs e)
{
strHello = wsc.GetHello(); this.rtb_Result.Text = strHello;
}

One-Way方法不适合于下列情况:

l         方法需要对结果轮询

l         方法需要同步

服务端使用WSE SoapSenderSoapRecevier

在进行本部分内容之前,我们需要安装WSE2.0。WSE支持面向消息的编程,为我们提供了SoapSender和SoapReceiver基类,它能够支持发送和接收SoapEnvelopes,同时它也通过SoapClient和SoapService提供了更多的事务支持。SoapSender和SoapReceiver在客户端和服务端同时实现,客户端使用SoapSender发送消息,同时可选择使用SoapReceiver接收消息;服务端使用SoapReceiver接收消息,同时也可以选择使用SoapSender发送通知和回应。

示例代码:

客户端:

    /// <summary>
/// 自定义的消息接收类
/// </summary>
public class MyReceiver: SoapReceiver
{
public static Form1 form;
private string strBody; protected override void Receive(SoapEnvelope envelope)
{
strBody = envelope.InnerText; ///注意:在进行此项之前,一定要把rtb_Result控件的属性设为Public
form.rtb_Result.Invoke(new EventHandler(UpdateBody));
} void UpdateBody(object sender, System.EventArgs e)
{
form.rtb_Result.Text = strBody;
}
}
/**************************************************/
/// <summary>
/// 用WSE实现异步调用
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void button4_Click(object sender, System.EventArgs e)
{
wsc.FireEvent();
}

Web Service端:

        private ArrayList Listeners
{
get
{
return (ArrayList)Application["Listeners"];
}
} [WebMethod]
public void AddListener(string listener)
{
ArrayList alist = (ArrayList)Application["Listeners"]; if(alist == null)
alist = new ArrayList(); alist.Add(listener); Application["Listeners"] = alist; } [WebMethod]
public void FireEvent()
{
int i; for(i = ;i < this.Listeners.Count;i++)
{
SoapEnvelope envelope = new SoapEnvelope(); envelope.SetBodyObject("Hello World!"); envelope.Context.Addressing.Action = new Action((string)(this.Listeners[i])); envelope.Context.Addressing.ReplyTo = new ReplyTo(new System.Uri((string)(this.Listeners[i]))); SoapSender peerProxy = new SoapSender(new System.Uri((string)(this.Listeners[i]))); peerProxy.Send(envelope);
}
}

服务端使用WSE 自定义SoapMSMQ传输

SoapMSMQ是一款开源软件,简化使用WSE进行MSMQ操作,下载地址:

http://www.codeproject.com/useritems/SoapMSMQ.asp

SoapMSMQ完全支持事务,具有如下特点:

l         在事务中,请求要被同步初始化

l         同步阶段排队请求,并且返回令牌

l         异步阶段处理各个事务

l         所有持有令牌的请求都保证会被处理,但可能会不成功

l         支持向客户端发送通知

对SoapMSMQ感兴趣的朋友可以下载下来后,做进一步的研究。

总结

异步方法调用改善了客户端的响应和用户体验,增加了服务端的可扩展性。当方法需要耗费大量的时间时,可以采用异步方式调用,提供系统并发处理的能力。对于异步方式的开发,我们可以有如上所述的广泛选择。

示例程序界面:

下载地址:http://files.cnblogs.com/Terrylee/AsyncDemo.rar

出处:http://www.cnblogs.com/Terrylee/archive/2005/12/05/290845.html

深入学习Web Service系列----异步开发模式的更多相关文章

  1. 构建安全的Xml Web Service系列之wse之证书存储位置

    原文:构建安全的Xml Web Service系列之wse之证书存储位置 我们在前几天对xml web service的安全性提出了一些建议,大家可以通过以下地址访问: 构建安全的Xml Web Se ...

  2. 构建安全的Xml Web Service系列之初探使用Soap头

    原文:构建安全的Xml Web Service系列之初探使用Soap头 Xml Web Service 从诞生那天就说自己都么都么好,还津津乐道的说internet也会因此而进入一个新纪元,可5年多来 ...

  3. 构建安全的Xml Web Service系列之如何察看SoapMessage

    原文:构建安全的Xml Web Service系列之如何察看SoapMessage 上一篇文章地址:构建安全的Xml Web Service系列一之初探使用Soap头 (5-22 12:53)     ...

  4. Web的Ajax应用开发模式(二)——Ajax开发模式分析

    寄语: 前天在查看一些公司的招聘要求时,看到有公司要求测试人员了解Ajax,故写此博文旨在帮助测试人员提高自身技术知识水平,愿与广大测试同胞共同进步.(欢迎纠错!!!) Web应用的传统开发模式总结: ...

  5. C# 开发XML Web Service与Java开发WebService

    一.web service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的请求,轻量 ...

  6. 构建安全的Xml Web Service系列之wse之错误代码详解

    原文:构建安全的Xml Web Service系列之wse之错误代码详解 WSE3.0现在还没有中文版的可以下载,使用英文版的过程中,难免会遇到各种各样的错误,而面对一堆毫无头绪的错误异常,常常会感到 ...

  7. 构建安全的Xml Web Service系列之SSL篇

    原文:构建安全的Xml Web Service系列之SSL篇 首先介绍一下SSL, SSL 的英文全称是 "Secure Sockets Layer" ,中文名为 "安全 ...

  8. Web Service简介与开发实例

    简介 1.1.Web Service基本概念 Web Service也叫XML Web Service WebService是一种可以接收从Internet或者Intranet上的其它系统中传递过来的 ...

  9. Java开发web的几种开发模式

    Java Web开发方案有多种可供选择,这里列举一些经典的开发模式进行横向比较,为Java Web的开发模式选择提供参考.除此之外还有好多方案(如Tapestry和Wicket等等)并不了解,这里就不 ...

随机推荐

  1. JavaWeb XML

    1. XML详解 1.1. XML介绍 1.1.1. 什么是XML XML的全称为eXtensible Markup Language,译为可扩展标记语言.XML语法上和HTML比较相似,但HTML中 ...

  2. kafka入门使用

    kafka版本0.11.0.1以上自带zookeeper,必须要求环境中有jdk,解压后进入目录 1.在kafka解压目录下下有一个config的文件夹,里面放置的是我们的配置文件 consumer. ...

  3. Pandas日期功能

    日期功能扩展了时间序列,在财务数据分析中起主要作用.在处理日期数据的同时,我们经常会遇到以下情况 - 生成日期序列 将日期序列转换为不同的频率 创建一个日期范围 通过指定周期和频率,使用date.ra ...

  4. SSH登陆阿里云服务器出现Permission denied (publickey)错误解决方案

    操作环境: 操作系统:Mac10.11.5 阿里云服务器:Ubuntu16.04 远程连接:SSH 注:首先我们已假设你已经自己生成了SSH秘钥,并已经配置到阿里云.绑定了自己的云服务器. 但是后来发 ...

  5. 解决Python字符串处理出现错误UnicodeDecodeError: ‘ascii’ codec can’t decode byte 0xe4 in position 108: ordinal not in range(128)

    今天做课程设计遇到了和数据库交互的地方,sqlite数据库设置成utf-8格式编码,插入到数据库中是正确的,但是当读取出来的时候就会出错,原因就是Python的str默认是ascii编码,搜集网上的资 ...

  6. Java多线程编程总结

    Java线程:概念与原理 Java线程:创建与启动 Java线程:线程栈模型与线程的变量 Java线程:线程状态的转换  Java线程:线程的同步与锁 Java线程:线程的交互 Java线程:线程的调 ...

  7. 各种WEB服务器自带的默认Servlet名称

    Tomcat, Jetty, JBoss, and GlassFish 自带的默认Servlet的名字 -- "default" Google App Engine 自带的 默认S ...

  8. nt":false,"tarball":"http://registry.npm.taobao.org/babel-preset-stag

    npm ERR! Unexpected end of input at 1:12777 npm ERR! nt":false,"tarball":"http:/ ...

  9. mongodb底层存储和索引原理——本质是文档数据库,无表设计,同时wiredTiger存储引擎支持文档级别的锁,MMAPv1引擎基于mmap,二级索引(二级是文档的存储位置信息『文件id + 文件内offset 』)

    MongoDB是面向文档的数据库管理系统DBMS(显然mongodb不是oracle那样的RDBMS,而仅仅是DBMS). 想想一下MySQL中没有任何关系型数据库的表,而由JSON类型的对象组成数据 ...

  10. 【python】类file文件处理

    [flush方法] 通常由于缓冲,write不将数据写入文件,而是写入内存的缓冲区,需要使用flush写入文件,并清空缓冲区 文件的flush方法的作用是强制清空缓存写入文件.默认每行flush一下? ...