web service实现原理与异步调用

来源:互联网 发布:快乐码字软件 编辑:程序博客网 时间:2024/03/29 01:26

    net2.0环境下,Web service中的每个方法,在Client端添加引用后生成的代理类中都会产生相应的异步方法和结束事件。我们可以利用这个异步方法和事件,轻松实现异步调用web service.

    简单范例

    假设在web service中定义了一个数据查询的方法:

  1. [WebMethod]
  2.    public DataSet ExecuteQuery(string SQL)
  3.         {
  4.             using (OracleConnection conn = new OracleConnection(connstrSQL))
  5.             {
  6.                 try
  7.                 {
  8.                     conn.Open();
  9.                     OracleCommand cmd = new OracleCommand(sql,conn);
  10.                     OracleDataAdapter ada = new OracleDataAdapter(cmd);
  11.                     DataSet ds = new DataSet();
  12.                     ada.Fill(ds);
  13.                     return ds;
  14.                 }
  15.                 catch (OracleException ex)
  16.                 {
  17.                     throw new Exception(ex.Message);
  18.                 }
  19.                 finally
  20.                 {
  21.                     conn.Close();
  22.                 }
  23.         }

    客户端:

  1. ///说明:
  2. ///panel1中放置了动态加载字样的图片等
  3. ///   
  4.  public partial class frmStock : Form
  5.     {
  6.         Service.MyService w = new Service.MyService(); //调用web service
  7.         public frmStock()
  8.         {
  9.             InitializeComponent();
  10.         }
  11.         private void frmStock_Load(object sender, EventArgs e)
  12.         {
  13.             //添加异步方法执行后触发事件
  14.             w.ExecuteQueryCompleted += new WMS.ExecuteQueryCompletedEventHandler(w_ExecuteQueryCompleted);
  15.         }
  16.         private void btnFind_Click(object sender, EventArgs e)
  17.         {
  18.             string sql = "select * from test";
  19.              w.ExecuteQueryAsync(sql);  //调用对应异步方法
  20.              ChangeStatus(true);
  21.         }
  22.         void w_ExecuteQueryCompleted(object sender, WMS.ExecuteQueryCompletedEventArgs e)
  23.         {
  24.            DataTable dt= e.Result.Tables[0];  //获得执行结果 e
  25.            ChangeStatus(false);
  26.            if (dt.Rows.Count <= 0)
  27.            {
  28.                MessageBox.Show("没有数据""information", MessageBoxButtons.OK, MessageBoxIcon.Information);
  29.                return;
  30.            }
  31.            gvshow.AutoGenerateColumns = false;
  32.            gvshow.DataSource = dt;
  33.         }
  34.         private void btnExit_Click(object sender, EventArgs e)
  35.         {
  36.             this.Close();
  37.         }
  38.         private void ChangeStatus(bool sign)
  39.         {
  40.             panel1.Visible = sign;
  41.             
  42.         }
  43.     }

   这样,可以

    1.避免了假死现象

    2.可以提供友好的用户体验

    

    实现原理

    web service 发布后,客户端添加引用,之后vs实际上在此时已经在后台生成本地代理类。之后看起来像是对web service的操作,实际上是对本地代理类的操作。代理类中处理网路访问逻辑,客户端的使用就象操作本地类一样简单便捷。

    客户端发出web service请求后,请求到达代理类,代理类处理请求从服务端获得SOAP数据包,而后进行数据处理后转发客户端。此中间涉及到的关于SOAP,WSDL等定义,简单的可以理解为:SOAP中定义了传输数据类型的格式和规则,而WSDL则以XML的形式定义了web service的消息和有关操作,通过http传输协议进行数据传输...

    那么代理类中到底如何定义的呢?

    我们可以通过自定义代理类的方式来分析代理类的详细信息。

    1.首先创建web service:Service.asmx

    2.IIS中建立虚拟目录并发布

    3.通过WSDL.exe工具生成代理类。

    打开SDK命令提示窗口,如下作业:

d:/Program Files/Microsoft Visual Studio 8/SDK/v2.0>wsdl http://localhost/Serve/Service.asmx?wsdl
Microsoft (R) Web Services Description Language Utility
[Microsoft (R) .NET Framework, Version 2.0.50727.42]
Copyright (C) Microsoft Corporation. All rights reserved.
Writing file 'd:/Program Files/Microsoft Visual Studio 8/SDK/v2.0/Service.cs'.

    其中service.cs就是生成的代理类,打开可见,其中涉及到异步方法,事件的生成。(部分代码如下)

 

  1.  /// <remarks/>
  2.     public event HelloWorldCompletedEventHandler HelloWorldCompleted;
  3.     
  4.     /// <remarks/>
  5.     public event showInfoCompletedEventHandler showInfoCompleted;
  6.     
  7.     /// <remarks/>
  8.     [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/HelloWorld", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]
  9.     public string HelloWorld() {
  10.         object[] results = this.Invoke("HelloWorld"new object[0]);
  11.         return ((string)(results[0]));
  12.     }
  13.     
  14.     /// <remarks/>
  15.     public System.IAsyncResult BeginHelloWorld(System.AsyncCallback callback, object asyncState) {
  16.         return this.BeginInvoke("HelloWorld"new object[0], callback, asyncState);
  17.     }
  18.     
  19.     /// <remarks/>
  20.     public string EndHelloWorld(System.IAsyncResult asyncResult) {
  21.         object[] results = this.EndInvoke(asyncResult);
  22.         return ((string)(results[0]));
  23.     }
  24.     
  25.     /// <remarks/>
  26.     public void HelloWorldAsync() {
  27.         this.HelloWorldAsync(null);
  28.     }
  29.     
  30.     /// <remarks/>
  31.     public void HelloWorldAsync(object userState) {
  32.         if ((this.HelloWorldOperationCompleted == null)) {
  33.             this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);
  34.         }
  35.         this.InvokeAsync("HelloWorld"new object[0], this.HelloWorldOperationCompleted, userState);
  36.     }
  37.     
  38.     private void OnHelloWorldOperationCompleted(object arg) {
  39.         if ((this.HelloWorldCompleted != null)) {
  40.             System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
  41.             this.HelloWorldCompleted(thisnew HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
  42.         }
  43.     }
  44.     
  45.     /// <remarks/>

    4.通过csc命令把service.cs生成为dll文件

    5.在专案中添加对此dll的引用

    6.这样对此dll的应用实际上就是通过这个代理类访问我们发布的web service.

 

    设计模式的应用

    此种方式的实现,在设计模式中就是有名的“代理模式”的实现方式。

原创粉丝点击