精彩的人生

          好好工作,好好生活

          BlogJava 首頁 新隨筆 聯系 聚合 管理
            147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

          ?

          在網絡中為了保證數據的實時性,需要對數據進行異步操作。Java Web Service和J2EE中的異步操作通過java消息機制來完成,消息機制是非常完善的技術了。而Microsoft的Web Service的異步功能是怎樣完成的呢?怎樣才能達到java的境地呢?當然,Microsoft有自己的一套。

          眾所周知,Web Service是靠SOAP協議進行數據傳輸的。而SOAP是基于XML技術之上的。SOAP協議是連接客戶和服務器的橋梁。而SOAP協議本身沒有異步功能,需要在客戶端實現異步調用。我們以一個簡單的Web Service的例子來說明這一點。

          一、MathService.asmx

          <%@ WebService Language="C#" Class="MathService" %>

          using System;

          using System.Web.Services;

          [WebService]

          public class MathService : WebService {

          [WebMethod]

          public float Add(float a, float b)

          {

          return a + b;

          }

          [WebMethod]

          public double Subtract(double a, double b)

          {

          return a - b;

          }

          [WebMethod]

          public float Multiply(float a, float b)

          {

          return a * b;

          }

          [WebMethod]

          public float Divide(float a, float b)

          {

          if (b==0) return -1;

          return a / b;

          }

          }

          這是個實現了加,減,乘,除的Web Service,任何客戶端程序都可以調用它。下面我們用wsdl(微軟公司提供)工具產生一個MathService.asmx 的客戶代理程序:wsdl /n:MyMath http://localhost/mathservice.asmx (假設MathService.asmx放在IIS服務器的根目錄) ,產生一個MathService.cs代理程序,默認是SOAP協議。

          二、MathService.cs:

          namespace MyMath{

          using System.Diagnostics;

          using System.Xml.Serialization;

          using System;

          using System.Web.Services.Protocols;

          using System.ComponentModel;

          using System.Web.Services;

          [System.Diagnostics.DebuggerStepThroughAttribute()]

          [System.ComponentModel.DesignerCategoryAttribute("code")]

          [System.Web.Services.WebServiceBindingAttribute(Name="MathServiceSoap", Namespace="http://tempuri.org/")]

          public class MathService : System.Web.Services.Protocols.SoapHttpClientProtocol {

          public MathService() {

          this.Url = "http://localhost/mathservice.asmx";

          }

          [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Add", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

          public System.Single Add(System.Single a, System.Single b) {

          object[] results = this.Invoke("Add", new object[] {

          a,

          b});

          return ((System.Single)(results[0]));

          }

          public System.IAsyncResult BeginAdd(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {

          return this.BeginInvoke("Add", new object[] {

          a,

          b}, callback, asyncState);

          }

          /// <remarks/>

          public System.Single EndAdd(System.IAsyncResult asyncResult) {

          object[] results = this.EndInvoke(asyncResult);

          return ((System.Single)(results[0]));

          }

          /// <remarks/>

          [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Subtract", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

          public System.Double Subtract(System.Double a, System.Double b) {

          object[] results = this.Invoke("Subtract", new object[] {

          a,

          b});

          return ((System.Double)(results[0]));

          }

          /// <remarks/>

          public System.IAsyncResult BeginSubtract(System.Double a, System.Double b, System.AsyncCallback callback, object asyncState) {

          return this.BeginInvoke("Subtract", new object[] {

          a,

          b}, callback, asyncState);

          }

          /// <remarks/>

          public System.Double EndSubtract(System.IAsyncResult asyncResult) {

          object[] results = this.EndInvoke(asyncResult);

          return ((System.Double)(results[0]));

          }

          /// <remarks/>

          [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Multiply", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

          public System.Single Multiply(System.Single a, System.Single b) {

          object[] results = this.Invoke("Multiply", new object[] {

          a,

          b});

          return ((System.Single)(results[0]));

          }

          /// <remarks/>

          public System.IAsyncResult BeginMultiply(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {

          return this.BeginInvoke("Multiply", new object[] {

          a,

          b}, callback, asyncState);

          }

          /// <remarks/>

          public System.Single EndMultiply(System.IAsyncResult asyncResult) {

          object[] results = this.EndInvoke(asyncResult);

          return ((System.Single)(results[0]));

          }

          /// <remarks/>

          [System.Web.Services.Protocols.SoapDocumentMethodAttribute("http://tempuri.org/Divide", RequestNamespace="http://tempuri.org/", ResponseNamespace="http://tempuri.org/", Use=System.Web.Services.Description.SoapBindingUse.Literal, ParameterStyle=System.Web.Services.Protocols.SoapParameterStyle.Wrapped)]

          public System.Single Divide(System.Single a, System.Single b) {

          object[] results = this.Invoke("Divide", new object[] {

          a,

          b});

          return ((System.Single)(results[0]));

          }

          /// <remarks/>

          public System.IAsyncResult BeginDivide(System.Single a, System.Single b, System.AsyncCallback callback, object asyncState) {

          return this.BeginInvoke("Divide", new object[] {

          a,

          b}, callback, asyncState);

          }

          /// <remarks/>

          public System.Single EndDivide(System.IAsyncResult asyncResult) {

          object[] results = this.EndInvoke(asyncResult);

          return ((System.Single)(results[0]));

          }

          }

          }

          之后我們用csc /t:library MathService.cs編譯并產生一個MathService.dll.

          現在我們可以寫任何的客戶程序去調用服務器上的MathService.asmx。

          如:WinForm, C#,ASPX等。

          下面我們寫一個test.cs去測試異步調用:

          三、test.cs:

          using System;

          public class test{

          public static void Main(){

          MyMath.MathService math = new MyMath.MathService();

          IAsyncResult result1 = math.BeginAdd(10,20,null,null);

          Object result=math.EndAdd(result1);

          Console.WriteLine("result =========="+result);

          }

          }

          我們看到它是先調用代理MathService.cs中的BeginAdd方法,然后狀態信息保存在IasyncResult中,直到調用了EndAdd方法才返回調用的確切值。本例是遠端調用MathService.asmx中的Add方法。

          那Microsoft到底怎樣實現客戶端的異步呢?設計模式又是怎樣的呢?

          異步模式所提供的革新之一就是調用方確定特定調用是否應是異步的。  對于被調用的對象,沒有必要執行附加的編程來用于支持其客戶端的異步行為;在該模式中異步委托提供此功能。公共語言運行庫處理調用方和被調用的對象視圖之間的差異。被調用的對象可以選擇顯式支持異步行為,這或者是因為它可以比一般結構更為有效地實現異步行為,或者是因為它想只支持其調用方的異步行為。但是,建議這種被調用的對象遵循公開異步操作的異步設計模式。

          類型安全是異步模式的另一項革新。尤其對于異步委托,針對 .NET 框架和公共語言運行庫的語言編譯器可令映射到規則 Invoke 方法的開始和結束操作(例如,BeginInvoke 和 EndInvoke)的方法簽名是類型安全的。這是十分重要的,因為編譯器為異步委托將同步調用拆分成開始和結束操作,使其能夠只傳遞有效參數。

          在此模式中所蘊含的基本想法如下所示:

          1.調用方確定特定調用是否應是異步的。

          2. 對于被調用的對象,沒有必要由其客戶端執行附加的編程來用于支持異步行為。公共語言運行庫結構應該能夠處理調用方和被調用的對象視圖之間的差異。

          3. 被調用的對象可以選擇顯式支持異步行為,這或者是因為它可以比一般結構更為有效地實現異步行為,或者是因為它想只支持其調用方的異步行為。但是,建議這種被調用的對象遵循公開異步操作的異步設計模式。

          4. 編譯器為 BeginInvoke 和 EndInvoke 以及異步委托生成類型安全方法簽名。

          5. .NET 框架提供支持異步編程模型所需的服務。此類服務的部分列表示例是:

          (1)同步基元,例如監視器和閱讀器編寫器鎖定。

          (2)線程和線程池。

          (3)同步構造,例如支持等候對象的容器。

          (4)向基礎結構片(例如 IMessage 對象和線程池)公開。

          該模式將一個同步調用拆分成各構成部分:開始操作、結束操作和結果對象。考慮以下示例,在其中可能要用大量時間來完成 Factorize 方法。

          public class PrimeFactorizer

          {

          public bool Factorize(int factorizableNum, ref int primefactor1, ref int primefactor2)

          {

          // Determine whether factorizableNum is prime.

          // If is prime, return true. Otherwise, return false.

          // If is prime, place factors in primefactor1 and primefactor2.

          }

          }

          如果遵循異步模式,則類庫編寫器添加 BeginFactorize 和 EndFactorize方法,這兩個方法將同步操作拆分成兩個異步操作:

          public class PrimeFactorizer

          {

          public bool Factorize(

              int factorizableNum,

              ref int primefactor1,

              ref int primefactor2)

          {

          // Determine whether factorizableNum is prime.

          // if is prime, return true; otherwise return false.

          // if is prime palce factors in primefactor1 and primefactor2

          }

          public IAsyncResult BeginFactorize(

             int factorizableNum,

             ref int primefactor1,

             ref int primefactor2,

             AsyncCallback callback,

             Object state)

          {

           // Begin the factorizing asynchronously, and return a result object,

          }

          public bool EndFactorize(

             ref int primefactor1,

             ref int primefactor2,

             IAsyncResult asyncResult

           )

          {

          // End (or complete) the factorizing, and

          // return the results,

          // and obtain the prime factors.

          }

          }

          服務器將異步操作拆分成兩個邏輯部分:采用來自客戶端的輸入并調用異步操作的部分,向客戶端提供異步操作結果的部分。

          除了異步操作所需的輸入外,第一部分還采用在完成異步操作時后要被調用的 AsyncCallback 委托。第一部分返回一個可等待的對象,該對象實現客戶端使用的 IAsyncResult 接口來確定異步操作的狀態。

          服務器還利用它返回到客戶端的可等待的對象來維護與異步操作關聯的任何狀態。通過提供可等待的對象,客戶端使用第二部分獲取異步操作的結果。

          可用于客戶端來啟動異步操作的選項有:

          在開始異步調用時提供回調委托。

           public class Driver1

             {

               public PrimeFactorizer primeFactorizer;

               public void Results(IAsyncResult asyncResult)

              {

               int primefactor1=0;

                int primefactor2=0;

                bool prime = primeFactorizer.EndFactorize(

                   ref primefactor1,

                   ref primefactor2,

                   asyncResult);

              }

               public void Work()

               {

                int factorizableNum=1000589023,

                int primefactor1=0;

                int primefactor2=0;

                Object state = new Object();

                primeFactorizer = new PrimeFactorizer();

                AsyncCallback callback = new Callback(this.Results);

                IAsyncResult asyncResult =                      primeFactorizer.BeginFactorize(

                 factorizableNum,

                 ref primefactor1,

                 ref primefactor2,

                 callback,

                 state);

              } 

          在開始異步調用時不提供回調委托。

          public class Driver2

          {

          public static void Work()

          {

          int factorizableNum=1000589023,

          int primefactor1=0;

          int primefactor2=0;

          Object state = new Object();

          PrimeFactorizer primeFactorizer = new PrimeFactorizer();

          AsyncCallback callback = new Callback(this.Results);

          IAsyncResult asyncResult = primeFactorizer.BeginFactorize(

          factorizableNum,

          ref primefactor1,

          ref primefactor2,

          callback,

          state);

          bool prime = primeFactorizer.EndFactorize(

          ref primefactor1,

          ref primefactor2,

          asyncResult);

          }

          }

          我們以.Net的一個例子來說明這一點:

          AsyncDelegate2.cs

          using System;

          using System.Threading;

          using System.Runtime.Remoting;

          using System.Runtime.Remoting.Messaging;

          public class Wak

          {

          public int Pat(int i)

          {

          Console.WriteLine("Hash: {0} Wak Pat", Thread.CurrentThread.GetHashCode());

          return i*2;

          }

          };

          public delegate int WakPatDelegate(int i);// 異步調用的委派.

          public class Simple

          {

          public static void SomeMethod(IAsyncResult ar)

          {

          // Obtain value from AsyncState object

          int value = Convert.ToInt32(ar.AsyncState);

          // Obtain results via EndInvoke

          int result = ((WakPatDelegate)((AsyncResult)ar).AsyncDelegate ).EndInvoke(ar);

          Console.WriteLine("Simple.SomeMethod (AsyncCallback): Result of {0} in Wak.Pak is {1} ",value, result);

          }

          public static void Main(String[] args)

          {

          Console.WriteLine("Thread Simple Context Sample");

          Console.WriteLine("");

          Console.WriteLine("Make an instance of a context-bound type Wak");

          Wak oWak = new Wak();

          int value=0;

          int result=0;

          Console.WriteLine("Make a sync call on the object");

          value = 10;

          result = oWak.Pat(value);

          Console.WriteLine("Result of {0} in Wak.Pak is {1} ",value, result);

          Console.WriteLine("Make single Async call on Context-bound object");

          WakPatDelegate wpD1 = new WakPatDelegate(oWak.Pat);

          value = 20;

          IAsyncResult ar1 = wpD1.BeginInvoke(value,null,null);

          ar1.AsyncWaitHandle.WaitOne();

          result = wpD1.EndInvoke(ar1);

          Console.WriteLine("Result of {0} in Wak.Pak is {1} ",value, result);

          Console.WriteLine("Make single Async call on Context-bound object - use AsyncCallback and StateObject");

          WakPatDelegate wpD2 = new WakPatDelegate(oWak.Pat);

          value = 30;

          IAsyncResult ar2 = wpD2.BeginInvoke(

          value,

          new AsyncCallback(Simple.SomeMethod),

          value

          );

          Console.WriteLine("Make multiple Async calls on Context-bound object");

          int asyncCalls = 5;

          IAsyncResult[] ars = new IAsyncResult[asyncCalls];

          WaitHandle[] whs = new WaitHandle[asyncCalls];

          int[] values = new int[asyncCalls];

          WakPatDelegate wpD3 = new WakPatDelegate(oWak.Pat);

          for (int i=0; i < asyncCalls; i++)

          {

          values[i] = i;

          ars[i] = wpD3.BeginInvoke(values[i],null,null);

          whs[i] = ars[i].AsyncWaitHandle;

          }

          WaitHandle.WaitAll(whs,1000, false);

          for (int i=0; i < asyncCalls; i++)

          {

          result = wpD3.EndInvoke(ars[i]);

          Console.WriteLine("Result of {0} in Wak.Pak is {1} ",values[i], result);

          }

          Console.WriteLine("");

          Console.WriteLine("Done");

          }

          }

              

          如果異步調用成功,將顯示:

          Thread Simple Context Sample

          Make an instance of a context-bound type Wak

          Make a sync call on the object

          Hash: 3 Wak Pat

          Result of 10 in Wak.Pak is 20

          Make single Async call on Context-bound object

          Hash: 16 Wak Pat

          Result of 20 in Wak.Pak is 40

          Make single Async call on Context-bound object - use AsyncCallback and StateObje

          ct

          Hash: 16 Wak Pat

          Make multiple Async calls on Context-bound object

          Simple.SomeMethod (AsyncCallback): Result of 30 in Wak.Pak is 60

          Hash: 16 Wak Pat

          Hash: 16 Wak Pat

          Hash: 16 Wak Pat

          Hash: 16 Wak Pat

          Hash: 16 Wak Pat

          Result of 0 in Wak.Pak is 0 

          Result of 1 in Wak.Pak is 2

          Result of 2 in Wak.Pak is 4

          Result of 3 in Wak.Pak is 6

          Result of 4 in Wak.Pak is 8

          Done

          原文地址:http://www.ccw.com.cn/htm/center/prog/02_8_23_6.asp

          posted on 2006-05-07 16:28 hopeshared 閱讀(2690) 評論(1)  編輯  收藏 所屬分類: Web Service

          Feedback

          # re: 轉:Web Service 的異步調用 2008-08-26 15:08 toni
          好東東  回復  更多評論
            

          主站蜘蛛池模板: 富阳市| 馆陶县| 高碑店市| 荆州市| 土默特左旗| 铁岭县| 绥中县| 株洲市| 蒙自县| 大渡口区| 拉萨市| 安乡县| 交城县| SHOW| 常德市| 阿荣旗| 布拖县| 莆田市| 台北市| 垫江县| 哈巴河县| 湘阴县| 永平县| 杭州市| 株洲县| 青海省| 辽中县| 竹溪县| 治县。| 屯门区| 页游| 建湖县| 栾川县| 新泰市| 布拖县| 高要市| 凌云县| 砀山县| 卫辉市| 偏关县| 苗栗市|