監(jiān)理公司管理系統(tǒng) | 工程企業(yè)管理系統(tǒng) | OA系統(tǒng) | ERP系統(tǒng) | 造價咨詢管理系統(tǒng) | 工程設計管理系統(tǒng) | 甲方項目管理系統(tǒng) | 簽約案例 | 客戶案例 | 在線試用
X 關閉

Web Service 的異步調(diào)用

申請免費試用、咨詢電話:400-8352-114

AMTeam.org

Web Service 的異步調(diào)用

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

眾所周知,Web Service是靠SOAP協(xié)議進行數(shù)據(jù)傳輸?shù)摹6鳶OAP是基于XML技術(shù)之上的。SOAP協(xié)議是連接客戶和服務器的橋梁。而SOAP協(xié)議本身沒有異步功能,需要在客戶端實現(xiàn)異步調(diào)用。我們以一個簡單的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;

}

}

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

二、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編譯并產(chǎn)生一個MathService.dll.

現(xiàn)在我們可以寫任何的客戶程序去調(diào)用服務器上的MathService.asmx。

如:WinForm, C#,ASPX等。

下面我們寫一個test.cs去測試異步調(diào)用:

三、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);

}

}

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

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

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

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

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

1.調(diào)用方確定特定調(diào)用是否應是異步的。

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

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

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

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

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

(2)線程和線程池。

(3)同步構(gòu)造,例如支持等候?qū)ο蟮娜萜鳌?/FONT>

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

該模式將一個同步調(diào)用拆分成各構(gòu)成部分:開始操作、結(jié)束操作和結(jié)果對象??紤]以下示例,在其中可能要用大量時間來完成 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.

}

}

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

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

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

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

在開始異步調(diào)用時提供回調(diào)委托。

 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);

    } 


在開始異步調(diào)用時不提供回調(diào)委托。

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);// 異步調(diào)用的委派.

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;

ars = wpD3.BeginInvoke(values,null,null);

whs = ars.AsyncWaitHandle;

}

WaitHandle.WaitAll(whs,1000, false);

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

{

result = wpD3.EndInvoke(ars);

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

}

Console.WriteLine("");

Console.WriteLine("Done");

}

}

如果異步調(diào)用成功,將顯示:

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

發(fā)布:2007-03-25 13:29    編輯:泛普軟件 · xiaona    [打印此頁]    [關閉]
相關文章:
石家莊OA系統(tǒng)
聯(lián)系方式

成都公司:成都市成華區(qū)建設南路160號1層9號

重慶公司:重慶市江北區(qū)紅旗河溝華創(chuàng)商務大廈18樓

咨詢:400-8352-114

加微信,免費獲取試用系統(tǒng)

QQ在線咨詢