深入学习Web Service系列----异步开发模式
概述
在本篇隨筆中,通過一些簡單的示例來說一下Web Service中的異步調(diào)用模式。調(diào)用Web Service方法有兩種方式,同步調(diào)用和異步調(diào)用。同步調(diào)用是程序繼續(xù)執(zhí)行前等候調(diào)用的完成,而異步調(diào)用在后臺繼續(xù)時,程序也繼續(xù)執(zhí)行,不必等待方法處理完成而直接返回。具體的調(diào)用流程見下圖:
?
對于同步調(diào)用方法而言,UI線程依賴于方法的實現(xiàn),方法執(zhí)行時間過長將導致UI無法及時與用戶進行交互。我們知道,在Windows客戶端中,每個進程都有單一的UI進程,在服務(wù)器中,可擴展性依賴于線程的使用。對于異步調(diào)用方法而言,能夠及時于用戶交互響應(yīng),從而提供了良好的用戶體驗;同時也可以改善服務(wù)器的可擴展性,將服務(wù)器與通訊問題隔離。
?
客戶端異步調(diào)用方法
在客戶端異步調(diào)用是完全基于Proxy的方法,異步行為最簡單的模式。Visual Studio和WSDL.EXE提供對它的直接支持。所以我們不必在Web服務(wù)應(yīng)用程序中編寫額外的代碼來處理異步調(diào)用。
遍及.NET Framework的異步調(diào)用有一個基礎(chǔ)的設(shè)計模式:Begin方法和End方法,他們分別用于開始和終止異步處理。Visual Studio和WSDL.exe生成了這兩種方法:
Begin<WebServiceMethodName>——該方法通知Web服務(wù)開始處理調(diào)用,并立即返回。該方法不返回Web服務(wù)調(diào)用所指定的數(shù)據(jù)類型,而是返回一種實現(xiàn)IasyncResult接口的數(shù)據(jù)類型。
End<WebServiceMethodName>——該方法通知Web服務(wù)返回先前啟動的Web方法所生成的結(jié)果。
IasyncResult接口包含了WaitHandle類型的AsyncWaitHandle特性。這個公共接口允許用戶的客戶應(yīng)用程序等待調(diào)用,而且,該接口將用Any或All語義(例如WaitHandle.WaitOne,WaitAny和WaitAll)作為信號通知客戶應(yīng)用程序。例如,如果想要客戶應(yīng)用程序異步等候一個Web方法,可調(diào)用WaitOne來處理要完成的Web服務(wù)。
一般來說,客戶端異步代理方法有兩種實現(xiàn)機制:使用同步對象和回調(diào)機制(也許你可能對用這個詞不習慣,實在找不到第二個詞來代替,暫且這樣稱呼吧)
同步對象
同步對象允許用戶對Web服務(wù)的方法進行調(diào)用(使用Begin方法),然后繼續(xù)處理。在后面的程序中,可以調(diào)用End方法,傳遞同步對象,以便得到調(diào)用結(jié)果。這種方式下,能夠繼續(xù)執(zhí)行函數(shù)中的程序流程,而不執(zhí)行回調(diào)處理。在這里調(diào)用WaitOne()方法會掛起當前線程,避免忙等待的發(fā)生,直到Web Services方法調(diào)用結(jié)束返回后,該線程才會被重新喚起。
示例代碼:
/// <summary> /// 利用同步對象實現(xiàn)異步調(diào)用 /// </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; }?
?
?
回調(diào)機制
從本質(zhì)上說,異步回調(diào)機制是委托的.NET等價物,它通過在異步操作完成時建立一個被調(diào)用的單獨方法來進行工作。調(diào)用應(yīng)用程序能夠繼續(xù)處理其他的任務(wù),直到回調(diào)函數(shù)被調(diào)用為止。這就意味著處理已經(jīng)完成了,應(yīng)用程序可以正常運行了。使用同步對象不同于回調(diào)機制的區(qū)別是,當檢查Web方法是否已經(jīng)完成,以及檢查Web方法中是否含有需要的結(jié)果時,我們無法對其進行控制,而在回調(diào)的情況中,Web方法一旦完成,這些工作就會被自動執(zhí)行。
示例代碼:
/// <summary> /// 顯示結(jié)果 /// </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> /// 用回調(diào)機制實現(xiàn)異步調(diào)用 /// </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); }?
?
?
使用回調(diào)機制還是同步對象取決于用戶所面臨的具體情況。在檢查異步調(diào)用是否完成時,如果愿意對處理過程進行控制,那么可以選擇使用同步對象。如果覺得自己編寫代碼來完成對Web服務(wù)的調(diào)用,且當方法一旦執(zhí)行完畢就立即由所調(diào)用的特殊函數(shù)來處理所返回的結(jié)果更適合一些,那么就更適合用回調(diào)機制。
在客戶端使用異步方法調(diào)用,可以改進UI響應(yīng)度,在服務(wù)器端不需要實現(xiàn)異步操作,對服務(wù)器來說是透明的,而且客戶端能夠在任何時間選擇阻塞。
?
服務(wù)端使用Soap One-Way方法
在服務(wù)器端使用One-Way方法實現(xiàn)異步調(diào)用,其實質(zhì)是將單項消息發(fā)送到端點。這種方式的特點是方法沒有返回值,客戶端方法不會從調(diào)用的服務(wù)器端方法中收到返回值;我們無法判斷方法結(jié)束的時間,對于結(jié)果需要顯式通知或者輪詢。
?
在Web 服務(wù)端,我們使用[SoapDocumentMethod]定義One-Way方法:
?[System.Web.Services.Protocols.SoapDocumentMethod(OneWay=true)]示例代碼:
/// <summary> /// One-Way方式的異步調(diào)用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方式的異步調(diào)用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???????? 方法需要對結(jié)果輪詢
l???????? 方法需要同步
?
服務(wù)端使用WSE SoapSender和SoapRecevier
在進行本部分內(nèi)容之前,我們需要安裝WSE2.0。WSE支持面向消息的編程,為我們提供了SoapSender和SoapReceiver基類,它能夠支持發(fā)送和接收SoapEnvelopes,同時它也通過SoapClient和SoapService提供了更多的事務(wù)支持。SoapSender和SoapReceiver在客戶端和服務(wù)端同時實現(xiàn),客戶端使用SoapSender發(fā)送消息,同時可選擇使用SoapReceiver接收消息;服務(wù)端使用SoapReceiver接收消息,同時也可以選擇使用SoapSender發(fā)送通知和回應(yīng)。
示例代碼:
?客戶端:
/// <summary>/// 自定義的消息接收類/// </summary>public class MyReceiver: SoapReceiver{public static Form1 form;private string strBody;protected override void Receive(SoapEnvelope envelope){strBody = envelope.InnerText;///注意:在進行此項之前,一定要把rtb_Result控件的屬性設(shè)為Publicform.rtb_Result.Invoke(new EventHandler(UpdateBody));}void UpdateBody(object sender, System.EventArgs e){form.rtb_Result.Text = strBody;}} /**************************************************/ /// <summary> /// 用WSE實現(xiàn)異步調(diào)用 /// </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 = 0;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);}}?
服務(wù)端使用WSE 自定義SoapMSMQ傳輸
SoapMSMQ是一款開源軟件,簡化使用WSE進行MSMQ操作,下載地址:
http://www.codeproject.com/useritems/SoapMSMQ.asp
SoapMSMQ完全支持事務(wù),具有如下特點:
l???????? 在事務(wù)中,請求要被同步初始化
l???????? 同步階段排隊請求,并且返回令牌
l???????? 異步階段處理各個事務(wù)
l???????? 所有持有令牌的請求都保證會被處理,但可能會不成功
l???????? 支持向客戶端發(fā)送通知
對SoapMSMQ感興趣的朋友可以下載下來后,做進一步的研究。
?
總結(jié)
異步方法調(diào)用改善了客戶端的響應(yīng)和用戶體驗,增加了服務(wù)端的可擴展性。當方法需要耗費大量的時間時,可以采用異步方式調(diào)用,提供系統(tǒng)并發(fā)處理的能力。對于異步方式的開發(fā),我們可以有如上所述的廣泛選擇。
?
示例程序界面:
下載地址:http://files.cnblogs.com/Terrylee/AsyncDemo.rar
出處:http://www.cnblogs.com/Terrylee/archive/2005/12/05/290845.html
轉(zhuǎn)載于:https://www.cnblogs.com/mq0036/p/4029497.html
總結(jié)
以上是生活随笔為你收集整理的深入学习Web Service系列----异步开发模式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Ioc Autofac心得
- 下一篇: android地图实时标记