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