<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    精彩的人生

    好好工作,好好生活

    BlogJava 首頁(yè) 新隨筆 聯(lián)系 聚合 管理
      147 Posts :: 0 Stories :: 250 Comments :: 0 Trackbacks

    深入學(xué)習(xí)Web Service系列之 異步開(kāi)發(fā)模式

    ——《深入學(xué)習(xí) Web Service 系列》之一

    Terrylee 2005 12 4

    概述

    在本篇隨筆中,通過(guò)一些簡(jiǎn)單的示例來(lái)說(shuō)一下 Web Service 中的異步調(diào)用模式。調(diào)用 Web Service 方法有兩種方式,同步調(diào)用和異步調(diào)用。同步調(diào)用是程序繼續(xù)執(zhí)行前等候調(diào)用的完成,而異步調(diào)用在后臺(tái)繼續(xù)時(shí),程序也繼續(xù)執(zhí)行,不必等待方法處理完成而直接返回。具體的調(diào)用流程見(jiàn)下圖:

    ?

    對(duì)于同步調(diào)用方法而言, UI 線程依賴于方法的實(shí)現(xiàn),方法執(zhí)行時(shí)間過(guò)長(zhǎng)將導(dǎo)致 UI 無(wú)法及時(shí)與用戶進(jìn)行交互。我們知道,在 Windows 客戶端中,每個(gè)進(jìn)程都有單一的 UI 進(jìn)程,在服務(wù)器中,可擴(kuò)展性依賴于線程的使用。對(duì)于異步調(diào)用方法而言,能夠及時(shí)于用戶交互響應(yīng),從而提供了良好的用戶體驗(yàn);同時(shí)也可以改善服務(wù)器的可擴(kuò)展性,將服務(wù)器與通訊問(wèn)題隔離。

    客戶端異步調(diào)用方法

    在客戶端異步調(diào)用是完全基于 Proxy 的方法,異步行為最簡(jiǎn)單的模式。 Visual Studio WSDL.EXE 提供對(duì)它的直接支持。所以我們不必在 Web 服務(wù)應(yīng)用程序中編寫(xiě)額外的代碼來(lái)處理異步調(diào)用。

    遍及 .NET Framework 的異步調(diào)用有一個(gè)基礎(chǔ)的設(shè)計(jì)模式: Begin 方法和 End 方法,他們分別用于開(kāi)始和終止異步處理。 Visual Studio WSDL.exe 生成了這兩種方法:

    Begin<WebServiceMethodName> ——該方法通知 Web 服務(wù)開(kāi)始處理調(diào)用,并立即返回。該方法不返回 Web 服務(wù)調(diào)用所指定的數(shù)據(jù)類型,而是返回一種實(shí)現(xiàn) IasyncResult 接口的數(shù)據(jù)類型。

    End<WebServiceMethodName> ——該方法通知 Web 服務(wù)返回先前啟動(dòng)的 Web 方法所生成的結(jié)果。

    IasyncResult 接口包含了 WaitHandle 類型的 AsyncWaitHandle 特性。這個(gè)公共接口允許用戶的客戶應(yīng)用程序等待調(diào)用,而且,該接口將用 Any All 語(yǔ)義(例如 WaitHandle.WaitOne WaitAny WaitAll )作為信號(hào)通知客戶應(yīng)用程序。例如,如果想要客戶應(yīng)用程序異步等候一個(gè) Web 方法,可調(diào)用 WaitOne 來(lái)處理要完成的 Web 服務(wù)。

    一般來(lái)說(shuō),客戶端異步代理方法有兩種實(shí)現(xiàn)機(jī)制:使用同步對(duì)象和回調(diào)機(jī)制(也許你可能對(duì)用這個(gè)詞不習(xí)慣,實(shí)在找不到第二個(gè)詞來(lái)代替,暫且這樣稱呼吧)

    同步對(duì)象

    同步對(duì)象允許用戶對(duì) Web 服務(wù)的方法進(jìn)行調(diào)用(使用 Begin 方法),然后繼續(xù)處理。在后面的程序中,可以調(diào)用 End 方法,傳遞同步對(duì)象,以便得到調(diào)用結(jié)果。這種方式下,能夠繼續(xù)執(zhí)行函數(shù)中的程序流程,而不執(zhí)行回調(diào)處理。在這里 調(diào)用 WaitOne() 方法會(huì)掛起當(dāng)前線程,避免忙等待的發(fā)生,直到 Web Services 方法調(diào)用結(jié)束返回后,該線程才會(huì)被重新喚起。

    示例代碼:

    ?1 /// ? <summary>
    ?2 /// ?利用同步對(duì)象實(shí)現(xiàn)異步調(diào)用
    ?3 /// ? </summary>
    ?4 /// ? <param?name="sender"></param>
    ?5 /// ? <param?name="e"></param>

    ?6 private ? void ?btn_AsyncClient_Click( object ?sender,?System.EventArgs?e)
    ?7 {
    ?8 ????IAsyncResult?ar? = ?wsc.BeginHello( this .txt_UserName.Text,? null ,? null );
    ?9
    10
    11 ????MessageBox.Show( " Continue?to?do?some?other?things " );
    12
    13 ????ar.AsyncWaitHandle.WaitOne();
    14
    15 ????strHello? = ?wsc.EndHello(ar);
    16
    17 ???? this .rtb_Result.Text? = ?strHello;
    18 }

    回調(diào)機(jī)制

    從本質(zhì)上說(shuō),異步回調(diào)機(jī)制是委托的 .NET 等價(jià)物,它通過(guò)在異步操作完成時(shí)建立一個(gè)被調(diào)用的單獨(dú)方法來(lái)進(jìn)行工作。調(diào)用應(yīng)用程序能夠繼續(xù)處理其他的任務(wù),直到回調(diào)函數(shù)被調(diào)用為止。這就意味著處理已經(jīng)完成了,應(yīng)用程序可以正常運(yùn)行了。使用同步對(duì)象不同于回調(diào)機(jī)制的區(qū)別是,當(dāng)檢查 Web 方法是否已經(jīng)完成,以及檢查 Web 方法中是否含有需要的結(jié)果時(shí),我們無(wú)法對(duì)其進(jìn)行控制,而在回調(diào)的情況中, Web 方法一旦完成,這些工作就會(huì)被自動(dòng)執(zhí)行。

    示例代碼:

    ?1 /// ? <summary>
    ?2 /// ?顯示結(jié)果
    ?3 /// ? </summary>
    ?4 /// ? <param?name="sender"></param>
    ?5 /// ? <param?name="e"></param>

    ?6 public ? void ?UpdateResult( object ?sender,?EventArgs?e)
    ?7 {
    ?8 ???? this .rtb_Result.Text? = ?strHello;
    ?9 }

    10
    11 public ? void ?OnHelloComplete(IAsyncResult?ar)
    12 {
    13 ????strHello? = ?wsc.EndHello(ar);
    14
    15 ???? this .rtb_Result.Invoke( new ?EventHandler(UpdateResult));
    16 }

    17
    18 /// ? <summary>
    19 /// ?用回調(diào)機(jī)制實(shí)現(xiàn)異步調(diào)用
    20 /// ? </summary>
    21 /// ? <param?name="sender"></param>
    22 /// ? <param?name="e"></param>

    23 private ? void ?btn_CallBack_Click( object ?sender,?System.EventArgs?e)
    24 {
    25 ????AsyncCallback?cb? = ? new ?AsyncCallback(OnHelloComplete);
    26
    27 ????wsc.BeginHello( this .txt_UserName.Text,?cb,? null );
    28 }

    使用回調(diào)機(jī)制還是同步對(duì)象取決于用戶所面臨的具體情況。在檢查異步調(diào)用是否完成時(shí),如果愿意對(duì)處理過(guò)程進(jìn)行控制,那么可以選擇使用同步對(duì)象。如果覺(jué)得自己編寫(xiě)代碼來(lái)完成對(duì) Web 服務(wù)的調(diào)用,且當(dāng)方法一旦執(zhí)行完畢就立即由所調(diào)用的特殊函數(shù)來(lái)處理所返回的結(jié)果更適合一些,那么就更適合用回調(diào)機(jī)制。

    在客戶端使用異步方法調(diào)用,可以改進(jìn) UI 響應(yīng)度,在服務(wù)器端不需要實(shí)現(xiàn)異步操作,對(duì)服務(wù)器來(lái)說(shuō)是透明的,而且客戶端能夠在任何時(shí)間選擇阻塞。

    服務(wù)端使用 Soap One-Way 方法

    在服務(wù)器端使用 One-Way 方法實(shí)現(xiàn)異步調(diào)用,其實(shí)質(zhì)是將單項(xiàng)消息發(fā)送到端點(diǎn)。這種方式的特點(diǎn)是方法沒(méi)有返回值,客戶端方法不會(huì)從調(diào)用的服務(wù)器端方法中收到返回值;我們無(wú)法判斷方法結(jié)束的時(shí)間,對(duì)于結(jié)果需要顯式通知或者輪詢。

    Web 服務(wù)端,我們使用 [SoapDocumentMethod] 定義 One-Way 方法:

    ?[System.Web.Services.Protocols.SoapDocumentMethod(OneWay = true )]

    示例代碼:

    ?1 /// ? <summary>
    ?2 /// ?One-Way方式的異步調(diào)用Set
    ?3 /// ? </summary>
    ?4 /// ? <param?name="sender"></param>
    ?5 /// ? <param?name="e"></param>

    ?6 private ? void ?btn_OneWay_Click( object ?sender,?System.EventArgs?e)
    ?7 {
    ?8 ????wsc.SetHello( this .txt_UserName.Text);????
    ?9 }

    10
    11 /// ? <summary>
    12 /// ?One-Way方式的異步調(diào)用Get
    13 /// ? </summary>
    14 /// ? <param?name="sender"></param>
    15 /// ? <param?name="e"></param>

    16 private ? void ?btn_onewayGet_Click( object ?sender,?System.EventArgs?e)
    17 {
    18 ????strHello? = ?wsc.GetHello();
    19
    20 ???? this .rtb_Result.Text? = ?strHello;
    21 }

    One-Way 方法不適合于下列情況:

    l???????? 方法需要對(duì)結(jié)果輪詢

    l???????? 方法需要同步

    服務(wù)端使用 WSE SoapSender SoapRecevier

    在進(jìn)行本部分內(nèi)容之前,我們需要安裝 WSE2.0 WSE 支持面向消息的編程,為我們提供了 SoapSender SoapReceiver 基類,它能夠支持發(fā)送和接收 SoapEnvelopes ,同時(shí)它也通過(guò) SoapClient SoapService 提供了更多的事務(wù)支持。 SoapSender SoapReceiver 在客戶端和服務(wù)端同時(shí)實(shí)現(xiàn),客戶端使用 SoapSender 發(fā)送消息,同時(shí)可選擇使用 SoapReceiver 接收消息;服務(wù)端使用 SoapReceiver 接收消息,同時(shí)也可以選擇使用 SoapSender 發(fā)送通知和回應(yīng)。

    示例代碼:

    ?客戶端:

    ?1 /// ? <summary>
    ?2 ???? /// ?自定義的消息接收類
    ?3 ???? /// ? </summary>

    ?4 ???? public ? class ?MyReceiver:?SoapReceiver
    ?5 ???? {
    ?6 ???????? public ? static ?Form1?form;
    ?7 ???????? private ? string ?strBody;
    ?8
    ?9 ???????? protected ? override ? void ?Receive(SoapEnvelope?envelope)
    10 ???????? {
    11 ????????????strBody? = ?envelope.InnerText;
    12
    13 ???????????? /// 注意:在進(jìn)行此項(xiàng)之前,一定要把rtb_Result控件的屬性設(shè)為Public
    14 ????????????form.rtb_Result.Invoke( new ?EventHandler(UpdateBody));
    15 ????????}

    16
    17 ???????? void ?UpdateBody( object ?sender,?System.EventArgs?e)
    18 ???????? {
    19 ????????????form.rtb_Result.Text? = ?strBody;
    20 ????????}

    21 ????}

    1 /// ? <summary>
    2 /// ?用WSE實(shí)現(xiàn)異步調(diào)用
    3 /// ? </summary>
    4 /// ? <param?name="sender"></param>
    5 /// ? <param?name="e"></param>

    6 private ? void ?button4_Click( object ?sender,?System.EventArgs?e)
    7 {
    8 ????wsc.FireEvent();
    9 }

    Web Service端:

    ?1 private ?ArrayList?Listeners
    ?2 ???????? {
    ?3 ???????????? get
    ?4 ???????????? {
    ?5 ???????????????? return ?(ArrayList)Application[ " Listeners " ];
    ?6 ????????????}

    ?7 ????????}

    ?8
    ?9 ????????[WebMethod]
    10 ???????? public ? void ?AddListener( string ?listener)
    11 ???????? {
    12 ????????????ArrayList?alist? = ?(ArrayList)Application[ " Listeners " ];
    13
    14 ???????????? if (alist? == ? null )
    15 ????????????????alist? = ? new ?ArrayList();
    16
    17 ????????????alist.Add(listener);
    18
    19 ????????????Application[ " Listeners " ]? = ?alist;
    20
    21 ????????}

    22
    23 ????????[WebMethod]
    24 ???????? public ? void ?FireEvent()
    25 ???????? {
    26 ???????????? int ?i;
    27
    28 ???????????? for (i? = ? 0 ;i? < ? this .Listeners.Count;i ++ )
    29 ???????????? {
    30 ????????????????SoapEnvelope?envelope? = ? new ?SoapEnvelope();
    31
    32 ????????????????envelope.SetBodyObject( " Hello?World! " );
    33
    34 ????????????????envelope.Context.Addressing.Action? = ? new ?Action(( string )( this .Listeners[i]));
    35
    36 ????????????????envelope.Context.Addressing.ReplyTo? = ? new ?ReplyTo( new ?System.Uri(( string )( this .Listeners[i])));
    37
    38 ????????????????SoapSender?peerProxy? = ? new ?SoapSender( new ?System.Uri(( string )( this .Listeners[i])));
    39
    40 ????????????????peerProxy.Send(envelope);
    41 ????????????}

    42 ????????}

    服務(wù)端使用 WSE 自定義 SoapMSMQ 傳輸

    SoapMSMQ 是一款開(kāi)源軟件,簡(jiǎn)化使用 WSE 進(jìn)行 MSMQ 操作,下載地址:

    http://www.codeproject.com/useritems/SoapMSMQ.asp

    SoapMSMQ 完全支持事務(wù),具有如下特點(diǎn):

    l???????? 在事務(wù)中,請(qǐng)求要被同步初始化

    l???????? 同步階段排隊(duì)請(qǐng)求,并且返回令牌

    l???????? 異步階段處理各個(gè)事務(wù)

    l???????? 所有持有令牌的請(qǐng)求都保證會(huì)被處理,但可能會(huì)不成功

    l???????? 支持向客戶端發(fā)送通知

    對(duì) SoapMSMQ 感興趣的朋友可以下載下來(lái)后,做進(jìn)一步的研究。

    總結(jié)

    異步方法調(diào)用改善了客戶端的響應(yīng)和用戶體驗(yàn),增加了服務(wù)端的可擴(kuò)展性。當(dāng)方法需要耗費(fèi)大量的時(shí)間時(shí),可以采用異步方式調(diào)用,提供系統(tǒng)并發(fā)處理的能力。對(duì)于異步方式的開(kāi)發(fā),我們可以有如上所述的廣泛選擇。

    示例程序界面:

    下載地址:

    http://www.cnblogs.com/Files/Terrylee/AsyncDemo.rar

    原文地址:http://terrylee.cnblogs.com/archive/2005/12/05/290845.html

    posted on 2006-05-07 15:28 hopeshared 閱讀(779) 評(píng)論(0)  編輯  收藏 所屬分類: Web Service
    主站蜘蛛池模板: 精品久久香蕉国产线看观看亚洲| 69成人免费视频无码专区| 免费国产不卡午夜福在线| 亚洲精品无码高潮喷水A片软| 久久久久久99av无码免费网站 | 亚洲成AV人片在线观看| 中文日本免费高清| 亚洲中文字幕无码爆乳AV| 国产精品黄页免费高清在线观看 | 四虎影视永久免费观看网址| WWW国产亚洲精品久久麻豆| 免费国产黄线在线观看| 亚洲av无码专区在线观看下载| 毛片a级毛片免费播放100| 亚洲AV无码AV吞精久久| 亚洲国产精品一区二区三区久久 | 亚洲资源最新版在线观看| 曰批全过程免费视频在线观看| 精品国产日韩久久亚洲| 免费人成在线观看网站品爱网日本| 成人免费观看男女羞羞视频| 国外亚洲成AV人片在线观看| 99视频精品全部免费观看| 亚洲一卡2卡3卡4卡乱码 在线| 免费观看四虎精品国产永久| 国产免费播放一区二区| 亚洲国产精品特色大片观看完整版| 精品免费久久久久久久| 亚洲日韩中文字幕一区| 久久影视国产亚洲| 真实国产乱子伦精品免费| 亚洲风情亚Aⅴ在线发布| 亚洲精品乱码久久久久久久久久久久 | 精品特级一级毛片免费观看| 亚洲狠狠婷婷综合久久久久| 无码精品A∨在线观看免费| 国产精品亚洲va在线观看| 亚洲AV无码一区东京热久久| 在线中文高清资源免费观看| GOGOGO高清免费看韩国| 亚洲欧洲日本在线观看|