深入學(xué)習(xí)Web Service系列之
異步開發(fā)模式
——《深入學(xué)習(xí) Web Service 系列》之一
Terrylee , 2005 年 12 月 4 日
概述
在本篇隨筆中,通過一些簡單的示例來說一下 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í)行時間過長將導(dǎo)致 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)機制(也許你可能對用這個詞不習(xí)慣,實在找不到第二個詞來代替,暫且這樣稱呼吧)
同步對象
同步對象允許用戶對 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é)束返回后,該線程才會被重新喚起。
示例代碼:


?2

?3

?4

?5

?6

?7



?8

?9

10

11

12

13

14

15

16

17

18

回調(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í)行。
示例代碼:


?2

?3

?4

?5

?6

?7



?8

?9

10

11

12



13

14

15

16

17

18


19

20

21

22

23

24



25

26

27

28

使用回調(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 方法:

示例代碼:


?2

?3

?4

?5

?6

?7



?8

?9

10

11


12

13

14

15

16

17



18

19

20

21

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)。
示例代碼:


?2

?3

?4

?5



?6

?7

?8

?9

10



11

12

13


14

15

16

17

18



19

20

21



2

3

4

5

6

7



8

9

Web Service端:

?2



?3

?4



?5

?6

?7

?8

?9

10

11



12

13

14

15

16

17

18

19

20

21

22

23

24

25



26

27

28

29



30

31

32

33

34

35

36

37

38

39

40

41

42

服務(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://www.cnblogs.com/Files/Terrylee/AsyncDemo.rar
原文地址:http://terrylee.cnblogs.com/archive/2005/12/05/290845.html