web service實現原理與非同步呼叫

iDotNetSpace發表於2010-05-18
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.         {
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.  /// 
    2.     public event HelloWorldCompletedEventHandler HelloWorldCompleted;
    3.     
    4.     /// 
    5.     public event showInfoCompletedEventHandler showInfoCompleted;
    6.     
    7.     /// 
    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.     /// 
    15.     public System.IAsyncResult BeginHelloWorld(System.AsyncCallback callback, object asyncState) {
    16.         return this.BeginInvoke("HelloWorld"new object[0], callback, asyncState);
    17.     }
    18.     
    19.     /// 
    20.     public  string EndHelloWorld(System.IAsyncResult asyncResult)
    21. {
    22.        object[] results = this.EndInvoke(asyncResult);
    23.         return ((string)(results[0]));
    24.     }
    25.     
    26.     /// 
    27.     public void HelloWorldAsync() {
    28.         this.HelloWorldAsync(null);
    29.     }
    30.     
    31.     /// 
    32.     public void HelloWorldAsync(object userState) {
    33.         if ((this.HelloWorldOperationCompleted == null)) {
    34.             this.HelloWorldOperationCompleted = new System.Threading.SendOrPostCallback(this.OnHelloWorldOperationCompleted);
    35.         }
    36.         this.InvokeAsync("HelloWorld"new object[0], this.HelloWorldOperationCompleted, userState);
    37.     }
    38.     
    39.     private void OnHelloWorldOperationCompleted(object arg) {
    40.         if ((this.HelloWorldCompleted != null)) {
    41.             System.Web.Services.Protocols.InvokeCompletedEventArgs invokeArgs = ((System.Web.Services.Protocols.InvokeCompletedEventArgs)(arg));
    42.             this.HelloWorldCompleted(thisnew HelloWorldCompletedEventArgs(invokeArgs.Results, invokeArgs.Error, invokeArgs.Cancelled, invokeArgs.UserState));
    43.         }
    44.     }
    45.     
    46.     /// 

    4.通過csc命令把service.cs生成為dll檔案

    5.在專案中新增對此dll的引用

    6.這樣對此dll的應用實際上就是通過這個代理類訪問我們釋出的web service.

來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/12639172/viewspace-663016/,如需轉載,請註明出處,否則將追究法律責任。

相關文章