扒开腿挺进岳湿润的花苞视频|将军边走边挺进她H树林|挺进朋友人妻张婉莹身体|岳脱得精光让我挺进去视频|第一次挺进莹莹的身体里视频|脱岳裙子从后面挺进去视频

新疆軟件開發(fā)

本站首頁(yè) 軟件開發(fā) 成功案例 公司新聞 公司簡(jiǎn)介 客服中心 軟件技術(shù) 網(wǎng)站建設(shè)
  您現(xiàn)在的位置: 新疆二域軟件開發(fā)公司 >> .Net技術(shù) >> 文章正文

透過(guò)HTTP進(jìn)行異步Web Service 呼叫

在撰寫使用 Web 服務(wù)的應(yīng)用程序時(shí),無(wú)可避免地,您必須處理透過(guò)網(wǎng)絡(luò)呼叫所涉及的潛在因素。在某些情況下,尤其是在擁有很大頻寬的私人網(wǎng)絡(luò)上,可能在半秒內(nèi)就完成呼叫,等待時(shí)間很短。不過(guò),如果您要透過(guò) Internet 傳送要求至遠(yuǎn)程位置,或要發(fā)出的呼叫需要很多處理時(shí)間,則您需要開始考慮長(zhǎng)時(shí)間延遲對(duì)您應(yīng)用程序的影響多大。例如,Microsoft® Windows® Forms 應(yīng)用程序在等待 Web 服務(wù)的呼叫傳回時(shí),看起來(lái)是凍結(jié)的。如果您是從 Microsoft® ASP.NET 網(wǎng)頁(yè)呼叫 Web 服務(wù),您會(huì)發(fā)現(xiàn),許多個(gè) Web 服務(wù)呼叫會(huì)讓網(wǎng)頁(yè)顯示速度慢好幾倍。如果您有一個(gè)應(yīng)用程序發(fā)出許多 Web 服務(wù)呼叫,則如何盡量有效率地呼叫它們,值得您思考。

許多這些問題的解決之道就是使 Web 服務(wù)呼叫異步化。異步呼叫會(huì)立即傳回,然后使用另一種機(jī)制來(lái)表示該呼叫何時(shí)實(shí)際完成。這可讓您的應(yīng)用程序執(zhí)行其它作業(yè),例如任何必要的背景處理、響應(yīng)使用者與 UI 的互動(dòng)、提供對(duì)于要求現(xiàn)行狀態(tài)的響應(yīng)、甚至起始其它 Web 服務(wù)呼叫。我們要看一看 Microsoft® .NET Framework 如何提供支持以透過(guò) HTTP 發(fā)出異步 Web 服務(wù)呼叫,以及我們?cè)谠S多一般實(shí)務(wù)中如何應(yīng)用它們。

建置區(qū)塊

Microsoft Visual Studio® .NET 選擇 [加入 Web 參考] 選項(xiàng)時(shí),會(huì)為您建立一個(gè)類別,它繼承自 System.Web.Services.Protocols.SoapHttpClientProtocolSoapHttpClientProtocol 有一個(gè)受保護(hù)的函式叫作 Invoke,當(dāng)您對(duì) Web 服務(wù)所公開的其中一個(gè)方法發(fā)出呼叫時(shí),實(shí)際上會(huì)使用此函式。對(duì)于 Web 服務(wù)的 WSDL 中所定義的每一個(gè) Web 方法,精靈會(huì)以適當(dāng)?shù)拿Q參數(shù)和回復(fù)值建立一個(gè)函式。每一個(gè)函式會(huì)呼叫 SoapHttpClientProtocol 類別的 Invoke 函式傳入?yún)?shù)信息,諸如此類。在本文件中,我建立一個(gè) Web 服務(wù),它使用的方法故意花費(fèi)很長(zhǎng)時(shí)間才傳回。這個(gè) Web 方法叫作 DelayedResponse,它以整數(shù)作為它的唯一參數(shù)并傳回一個(gè)字符串。[加入 Web 參考] 選項(xiàng)會(huì)為此方法產(chǎn)生下列 Proxy 程序代碼:

Public Function DelayedResponse(ByVal waitPeriod As Integer) _
        As String
    Dim results() As Object _
        = Me.Invoke("DelayedResponse", _
                    New Object() {waitPeriod})
    Return CType(results(0),String)
End Function
 

Invoke 方法使用兩個(gè)參數(shù):一個(gè)函式名稱和一個(gè)保留要傳遞至函式的參數(shù)之對(duì)象數(shù)組。Invoke 方法傳回對(duì)象數(shù)組,在本范例中,它只包含一個(gè)元素—從我們的函式傳回的字符串。這是發(fā)出同步呼叫的機(jī)制,這些呼叫要等到接收響應(yīng)之后才傳回。

SoapHttpClientProtocol 類別也有一個(gè)叫作 BeginInvoke 的方法,它是用來(lái)激活異步要求的機(jī)制。[加入 Web 參考] 所建立的類別也會(huì)建立一個(gè)叫作 BeginDelayedResponse 的公用函式來(lái)配合我們之前看過(guò)的區(qū)塊式 DelayedResponse 函式。BeginDelayedResponse 的程序代碼顯示如下。

Public Function BeginDelayedResponse( _
        ByVal waitPeriod As Integer, _
        ByVal callback As System.AsyncCallback, _
        ByVal asyncState As Object) As System.IAsyncResult
   Return Me.BeginInvoke("DelayedResponse", _
                         New Object() {waitPeriod}, _
                         callback, _
                         asyncState)
End Function

BeginDelayedResponse 使用 BeginInvoke 方法,它在許多方面類似我們之前使用過(guò)的 Invoke 方法。前兩個(gè)參數(shù)與 Invoke 方法使用的參數(shù)相同。不過(guò),BeginInvoke 還有兩個(gè)額外參數(shù),而且它不再傳回對(duì)象數(shù)組。不過(guò),其主要差異是 BeginInvoke 會(huì)立刻傳回,而不等待 Web 服務(wù)呼叫完成。

BeginInvoke 的兩個(gè)額外參數(shù)的第一個(gè)叫作 System.AsyncCallback。這就是所謂的委派,基本上它是一個(gè)用來(lái)宣告 Managed 程序代碼中的函式指針的機(jī)制。在本范例中,一旦 Web 方法呼叫完成且我們收到響應(yīng),則會(huì)呼叫此函式。

BeginInvoke 的最后一個(gè)參數(shù)就叫作 asyncState,它被宣告為對(duì)象類型。這可以是您要用來(lái)追蹤此要求的任何項(xiàng)目。您可以對(duì)許多不同的異步要求使用相同的回呼函式,以便區(qū)別某個(gè)呼叫的響應(yīng)與另一個(gè)呼叫的響應(yīng),您可以把關(guān)于該呼叫的信息放在 asyncState 參數(shù)中,它將供您的回呼函式使用。

關(guān)于 BeginInvoke 還有一點(diǎn)不同,即它傳回的內(nèi)容。很顯然,如果呼叫未完成,則它不能傳回響應(yīng)資料至 Web 方法。它傳回的是 System.IAsyncResult 接口指針。您可以使用 IAsyncResult 接口指針取得關(guān)于該要求的信息。IAsyncResult 顯示四個(gè)公用屬性,如下所示:

屬性

說(shuō)明

AsyncState

這是傳入 BeginInvoke 方法的第四個(gè)參數(shù)的資料。

AsyncWaitHandle

這是 WaitHandle 對(duì)象,可用來(lái)封鎖執(zhí)行緒目前的執(zhí)行,直到有一或多個(gè) Web 服務(wù)呼叫完成為止。

CompletedSynchronously

此參數(shù)不適用于 Web 服務(wù)呼叫。IAsyncResult 接口是用于一些 I/O 作業(yè),此屬性可讓您知道異步 I/O 作業(yè)要求是否太快完成,它甚至在 Begin 函式傳回之前完成。

IsCompleted

這是一個(gè)旗標(biāo),您可用它來(lái)判斷呼叫是否完成。

IAsyncResult 指針是最后可讓您和系統(tǒng)分辨不同的異步完成的指針。它也提供您不同選項(xiàng)來(lái)判斷呼叫何時(shí)完成。我們看看如何使用這些選項(xiàng)。

一如前述,[加入 Web 參考] 選項(xiàng)會(huì)為使用 BeginInvoke 的服務(wù)所提供的每一個(gè) Web 方法建立一個(gè)函式。在我們的范例中,所產(chǎn)生的函式叫作 BeginDelayedResponse,它是 BeginInvoke 方法的一個(gè)極輕巧的包裝函式,它顯示 Web 呼叫方法的參數(shù)以及 BeginInvoke 提供的 callback asyncState 參數(shù)。接下來(lái),我們要看看用來(lái)提出異步要求和判斷何時(shí)完成要求的三個(gè)選項(xiàng)。

發(fā)出異步呼叫的三個(gè)選項(xiàng)

每一個(gè)應(yīng)用程序都不一樣,因此,發(fā)出異步呼叫的案例對(duì)某些應(yīng)用程序可能有效,但不一定對(duì)其他應(yīng)用程序有效。在提供發(fā)出異步呼叫的方式上,.NET Framework 有很大的彈性。您可以輪詢看看何時(shí)完成要求、封鎖 WaitHandle 或等待回呼函式。現(xiàn)在我們個(gè)別來(lái)看一看這些方式。

輪詢完成狀態(tài)

BeginDelayedResponse 函式傳回的 IAsyncResult 接口有一個(gè) IsCompleted 屬性,可檢查此屬性來(lái)判斷是否完成要求。您可以輪詢此屬性,直到它傳回 True 值為止。示范此方式的簡(jiǎn)短程序代碼如下所示:

' 輪詢會(huì)束縛處理器的程序代碼
Dim proxy as New localhost.Service1()
Dim result as IAsyncResult
Result = proxy.BeginDelayedResponse(2000, _
                                    Nothing, _
                                    Nothing)
While (result.IsCompleted = False)
    ' 執(zhí)行一些處理
        ...
Wend
Dim response as String
response = proxy.EndDelayedResponse(result)

輪詢完成狀態(tài)是一個(gè)很直接的方式,但它的確有一些缺點(diǎn)。此程序代碼顯示如何對(duì) BeginDelayedResponse 發(fā)出起始呼叫,它傳遞數(shù)字 2000 作為要傳至 Web 方法的參數(shù),然后將回呼和 asyncState 設(shè)定為 Nothing。然后我們有一個(gè) while 循環(huán)來(lái)輪詢 IsCompleted 屬性,直到它為 True 為止。當(dāng)呼叫完成且 IsCompleted 屬性設(shè)定為 True 時(shí),我們會(huì)脫離 while 循環(huán),然后我們使用 [加入 Web 參考] 產(chǎn)生的類別中的另一個(gè)函式叫作 EndDelayedResponse,來(lái)取得響應(yīng)。EndDelayedResponse SoapHttpClientProtocol 類別的 EndInvoke 方法的包裝函式,而且是從 Web 方法呼叫取得傳回的資料的機(jī)制。當(dāng)您知道 Web 服務(wù)呼叫完成時(shí)即可使用;它傳回的信息與 Invoke 方法傳回給區(qū)塊式呼叫的信息一樣。在所有三個(gè)異步案例中,我們會(huì)使用 EndDelayedResponse 方法取得 Web 服務(wù)呼叫的結(jié)果。請(qǐng)注意,如果在完成要求之前呼叫 EndDelayedResponse,則它直接封鎖,直到要求真正完成為止。

在使用輪詢判斷呼叫是否完成時(shí),您需要注意的其中一個(gè)問題是,您一不小心就會(huì)消耗掉很多的機(jī)器 CPU 周期。例如,如果 while 循環(huán)內(nèi)沒有程序代碼,則執(zhí)行此程序代碼的執(zhí)行緒可占據(jù)您機(jī)器上的大部份資源。事實(shí)上,它會(huì)吃掉很多處理時(shí)間,使得要傳送 Web 服務(wù)要求和接收響應(yīng)的基礎(chǔ)程序代碼因而延遲。因此,使用輪詢時(shí)要小心。

如果您真的想要等到 Web 服務(wù)要求完成,您也許可以使用我們接下來(lái)要看的 WaitHandle 方式。不過(guò),如果您有很多處理要完成,而且您只想要偶而檢查一下 Web 服務(wù)呼叫是否結(jié)束,那么使用輪詢并不是一個(gè)壞的方案。許多時(shí)候,應(yīng)用程序會(huì)使用輪詢與其中另一個(gè)異步方式的組合。例如,您可以同步發(fā)出 Web 服務(wù)呼叫,因?yàn)槟幸恍┍尘疤幚硪獔?zhí)行,可是一旦背景處理執(zhí)行完畢,您想要封鎖直到 Web 服務(wù)完成為止。在此情況下,您可以在執(zhí)行處理時(shí)偶而輪詢一下,但是一旦背景處理完成,就使用 WaitHandle 來(lái)等候結(jié)果。

使用 WaitHandle

當(dāng)您需要發(fā)出異步呼叫,但您不想釋放目前在執(zhí)行的執(zhí)行緒,則 WaitHandle 很好用。例如,如果您從 ASP.NET 應(yīng)用程序內(nèi)發(fā)出異步 Web 服務(wù)呼叫,然后從處理 ASP.NET 應(yīng)用程序的事件中返回,則您可能沒有機(jī)會(huì)在傳回給使用者的資料中并入 Web 服務(wù)呼叫中的資料。運(yùn)用 WaitHandle,您就可以在發(fā)出 Web 服務(wù)呼叫之后做一些處理,然后封鎖直到 Web 服務(wù)呼叫完成為止。如果您要從 ASP.NET 網(wǎng)頁(yè)內(nèi)發(fā)出多個(gè) Web 服務(wù)呼叫,則 WaitHandle 特別有用。

WaitHandle 對(duì)象的存取權(quán)是由 BeginDelayedResponse 函式傳回的 IAsyncResult 提供。下列程序代碼顯示使用 WaitHandle 方式的簡(jiǎn)單案例。

' 簡(jiǎn)單的 WaitHandle 程序代碼 
Dim proxy As New localhost.Service1()
Dim result As IAsyncResult
result = proxy.BeginDelayedResponse(2000, Nothing, Nothing)
'  做一些處理。
'       ...
'  處理完成。等候完成。
result.AsyncWaitHandle.WaitOne()
Dim response As String
response = proxy.EndDelayedResponse(result)

在上述程序代碼中,我們使用了 WaitHandle 對(duì)象的 WaitOne 方法來(lái)等候這個(gè)控制代碼。WaitHandle 類別中也有靜態(tài)方法,叫作 WaitAll WaitAny。這兩個(gè)靜態(tài)方法以 WaitHandle 數(shù)組作為參數(shù),它們可能在所有呼叫完成后才傳回,或一有呼叫完成即傳回,視您呼叫的函式而定。假設(shè)您叫作三個(gè)不同的 Web 服務(wù)。您可以異步地呼叫每一個(gè)服務(wù),把 WaitHandle 放在每一個(gè)的數(shù)組中,然后呼叫 WaitAll 方法直到它們完成為止。這可讓 Web 服務(wù)呼叫同時(shí)執(zhí)行。如果您同步執(zhí)行此動(dòng)作,則無(wú)法并行地執(zhí)行它們,導(dǎo)致執(zhí)行時(shí)間變成三倍左右。

請(qǐng)注意,WaitOneWaitAll WaitAny 方法都有以逾時(shí) (Timeout) 作為參數(shù)的選項(xiàng)。這可讓您控制您要等候 Web 服務(wù)完成的時(shí)間。如果方法逾時(shí),它們會(huì)傳回 False 值。這可讓您在重新等候之前執(zhí)行更多處理,或讓您有機(jī)會(huì)取消要求。

使用回呼

執(zhí)行異步 Web 服務(wù)呼叫的第三個(gè)方式是使用回呼。如果您要發(fā)出很多同步 Web 服務(wù)呼叫,則使用回呼很有效率。它在 Web 服務(wù)呼叫的結(jié)果上執(zhí)行背景處理很有幫助。不過(guò),它是比其它兩個(gè)方法更復(fù)雜的方式。在 Microsoft Windows® 應(yīng)用程序中使用回呼特別適合,因?yàn)檫@可避免封鎖 Window 的訊息執(zhí)行緒。

回呼會(huì)在 Web 服務(wù)呼叫完成時(shí)導(dǎo)致回呼函式被呼叫。不過(guò),在發(fā)出原始 BeginInvoke 呼叫的執(zhí)行緒內(nèi)容中,不可呼叫回呼函式。這會(huì)造成傳送指令至 Windows Form 應(yīng)用程序的控件時(shí)產(chǎn)生問題,因?yàn)槟切┲噶畋仨毷菑奶囟▓?zhí)行緒呼叫,該執(zhí)行緒為該特定 Window 處理訊息處理。還有,有一個(gè)方法可解決此問題。

下列程序代碼顯示一個(gè)簡(jiǎn)單案例,它使用回呼且 Web 服務(wù)呼叫的結(jié)果會(huì)顯示在卷標(biāo)控件中。

Dim proxy as localhost.Service1
Private Delegate Sub MyDelegate(ByVal response As String)
 
Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Button1.Click
    proxy = New localhost.Service1()
    proxy.BeginDelayedResponse(2000, _
            New AsyncCallback(AddressOf Me.ServiceCallback), _
            Nothing)
End Sub
 
Private Sub ServiceCallback(ByVal result As IAsyncResult)
    Dim response As String
    response = proxy.EndDelayedResponse(result)
    Label1.Invoke( _
        New MyDelegate(AddressOf Me.DisplayResponse), _
        New Object() {response})
End Sub
 
Private Sub DisplayResponse(ByVal response As String)
    Label1.Text = response
End Sub

在此程序代碼中,我們呼叫 Button1_Click 事件中的 BeginDelayedResponse,然后從子程序傳回。請(qǐng)注意,本案例不傳遞 Nothing 作為第二個(gè)參數(shù),而是傳遞 AsyncCallback 對(duì)象;旧,這只是包裝回呼函式地址的一個(gè)方式,叫作 ServiceCallback。ServiceCallback 函式必須是一個(gè)子程序,它采取 IAsyncResult 類型的單一參數(shù)。SoapHttpClientProtocol 類別將呼叫此函式,并將提供對(duì)應(yīng)完成的 Web 服務(wù)呼叫的 IAsyncResult 接口指針。同樣地,我們使用 EndDelayedResponse 方法取得結(jié)果,但現(xiàn)在我們有一個(gè)小問題。

因?yàn)榛睾艨赡懿辉?/FONT> Window 的主要執(zhí)行緒中,所以我們需要使用不同的 Invoke 方法來(lái)設(shè)定 Window 中的卷標(biāo)文字。所有控件都有 Invoke 方法供您呼叫,以便呼叫一個(gè)在其主要訊息執(zhí)行緒中執(zhí)行的函式。在卷標(biāo)控件上使用 Invoke 類似我們已經(jīng)看過(guò)的其它一些內(nèi)容。我們必須提供要它呼叫的函式地址給 Invoke,而且我們要在對(duì)象數(shù)組中包括要傳給該函式的任何參數(shù),作為第二個(gè)參數(shù)。在此范例中,我們必須宣告一個(gè)叫作 MyDelegate 的委派類型,來(lái)通知 Invoke 方法我們要它呼叫的函式語(yǔ)法。在此范例中,此函式叫作 DisplayResponse,且只有一個(gè)參數(shù)—從 Web 服務(wù)呼叫傳回的字符串。將在卷標(biāo)控件的適當(dāng)執(zhí)行緒內(nèi)呼叫 DisplayResponse,而且它在設(shè)定應(yīng)用程控項(xiàng)文字方面沒有問題。

進(jìn)階議題

到目前為止,我們看過(guò)的范例都很直接。它們做了許多的假設(shè),例如我們的 Web 服務(wù)呼叫成功,并簡(jiǎn)化為一次僅發(fā)出單一呼叫的事實(shí),F(xiàn)在我們要看看有多個(gè) Web 服務(wù)呼叫的案例。我們要看看如何處理這些呼叫可能產(chǎn)生的錯(cuò)誤,并看看必要時(shí)如何取消呼叫。

使用 asyncState

我們先看一個(gè)范例,其中我們除了 Nothing 之外還傳遞其它項(xiàng)目作為 BeginDelayedResponse 呼叫的最后一個(gè)參數(shù)。如果您還記得,這是 asyncState 參數(shù),它直接宣告為一個(gè)對(duì)象,F(xiàn)在我們要使用此參數(shù)來(lái)發(fā)出多個(gè) Web 服務(wù)呼叫,使響應(yīng)與適當(dāng)?shù)囊螽a(chǎn)生關(guān)聯(lián)。

我現(xiàn)在要看的案例是對(duì) DelayedResponse Web 方法發(fā)出三個(gè)不同的呼叫。然后它會(huì)在我的 Windows 應(yīng)用程序的三個(gè)不同卷標(biāo)控件中顯示這些呼叫的結(jié)果。第一個(gè)呼叫的結(jié)果應(yīng)該顯示在第一個(gè)卷標(biāo),第二個(gè)呼叫的結(jié)果應(yīng)該顯示在第二個(gè)卷標(biāo),第三個(gè)呼叫的結(jié)果應(yīng)該顯示在第三個(gè)卷標(biāo)。我要對(duì)每一個(gè) Web 服務(wù)呼叫使用相同的回呼函式,而且為了判斷哪一個(gè)卷標(biāo)配哪一個(gè)呼叫,我會(huì)以 asyncState 參數(shù)傳遞卷標(biāo)對(duì)象。為了制造更多的混淆,我讓每一個(gè)呼叫要完成所花的時(shí)間隨機(jī)化。其做法的程序代碼顯示如下。

Dim proxy As localhost.Service1
Private Delegate Sub LabelDelegate( _
    ByVal responseLabel As Label, _
    ByVal response As String)
 
Private Sub Button1_Click(ByVal sender As System.Object, _
        ByVal e As System.EventArgs) Handles Button7.Click
    proxy = New localhost.Service1()
    ClearForm()
    Dim r As New Random()
 
    proxy.BeginDelayedResponse(r.Next(1, 10000), _
            New AsyncCallback(AddressOf Me.ServiceCallback), _
            Label1)
    proxy.BeginDelayedResponse(r.Next(1, 10000), _
            New AsyncCallback(AddressOf Me.ServiceCallback), _
            Label2)
    proxy.BeginDelayedResponse(r.Next(1, 10000), _
            New AsyncCallback(AddressOf Me.ServiceCallback), _
            Label3)
End Sub
 
Private Sub ServiceCallback(ByVal result As IAsyncResult)
    Dim response As String
    response = proxy.EndDelayedResponse(result)
    Dim responseLabel As Label = result.AsyncState
    responseLabel.Invoke( _
        New LabelDelegate(AddressOf Me.DisplayResponses), _
        New Object() {responseLabel, response})
End Sub
 
Private Sub DisplayResponses(ByVal responseLabel As Label, _
                             ByVal response As String)
    responseLabel.Text = response
    Form1.ActiveForm.Refresh()
End Sub

透過(guò)傳至回呼的 IAsyncResult 參數(shù),傳入 asyncState 參數(shù)的卷標(biāo)對(duì)象可在我們的回呼函式中使用。我們也修改了前一個(gè)范例中的委派,來(lái)采用另一個(gè)參數(shù)。另一個(gè)參數(shù)同樣是卷標(biāo),因此委派知道哪一個(gè)控件要設(shè)定文字。

也許您常常要傳遞更多信息,而不止是透過(guò) asyncState 的單一對(duì)象。因?yàn)?/FONT> asyncState 僅宣告為一個(gè)對(duì)象,因此也可以用它來(lái)傳遞復(fù)合信息,例如對(duì)象數(shù)組或您要使用的一些復(fù)合結(jié)構(gòu)。在我們的案例中,我們只使用一個(gè) Proxy 對(duì)象,但是在某些案例中,您可能有不同的 Proxy 對(duì)象給每一個(gè) Web 服務(wù)呼叫。如果是這種情況,您也可以在 asyncState 資料中并入該 Proxy 對(duì)象。Web 服務(wù)呼叫的任何其它特定資料也可以考慮并入其中。

偵測(cè)錯(cuò)誤

如果您習(xí)慣于發(fā)出同步 Web 服務(wù)呼叫,那么您可能也習(xí)慣透過(guò)以包裝遠(yuǎn)程呼叫的 try...catch 區(qū)塊來(lái)偵測(cè)錯(cuò)誤。對(duì)異步呼叫做同樣的事似乎令人感到困惑。我必須在 try...catch 區(qū)塊中包裝 BeginDelayedResponse EndDelayedResponse?也許我必須兩個(gè)都包裝!

其實(shí),對(duì)于正常 SOAP 錯(cuò)誤以及其它與傳送相關(guān)的錯(cuò)誤,我們只需要在 try...catch 區(qū)塊中包裝 EndDelayedResponse 呼叫。BeginDelayedResponse 呼叫不會(huì)產(chǎn)生錯(cuò)誤,因?yàn)樗鼤?huì)立刻傳回,而不會(huì)等候是否有任何問題。當(dāng)您在等待回呼被呼叫,或等待 Wait 呼叫解除封鎖時(shí),并不會(huì)隨機(jī)發(fā)生錯(cuò)誤。所發(fā)生的錯(cuò)誤會(huì)透過(guò)您使用的機(jī)制來(lái)觸發(fā)完成,機(jī)制可以是將 IsCompleted 屬性設(shè)定為 True、或是觸發(fā) WaitHandle 或是呼叫回呼。唯有當(dāng)您呼叫 EndDelayedResponse 時(shí)才會(huì)觸發(fā)錯(cuò)誤,它提供您關(guān)于失敗的信息。

為了證明我的應(yīng)用程序有可能失敗,我在回呼函式中的 EndDelayedResponse 呼叫周圍增加了一個(gè) try...catch 區(qū)塊。我順便修改了失敗的響應(yīng)文字。

Private Sub ServiceCallback(ByVal result As IAsyncResult)
    Dim response As String
    Try
        response = proxy.EndDelayedResponse(result)
    Catch e As Exception
        Response = "失敗"
    End Try
    Dim responseLabel As Label = result.AsyncState
    responseLabel.Invoke( _
        New LabelDelegate(AddressOf Me.DisplayResponses), _
        New Object() {responseLabel, response})
End Sub

中止要求

在應(yīng)用程序中使用異步要求的其中一個(gè)好處是,當(dāng)呼叫完成時(shí)您不必鎖定使用者接口。當(dāng)然,如果您要讓應(yīng)用程序使用者繼續(xù)與應(yīng)用程序互動(dòng),那么您可以并入的一個(gè)極常見的功能,就是取消未完成要求的一個(gè)按鈕。如果基于某種原因,Web 服務(wù)呼叫需要很長(zhǎng)的時(shí)間才會(huì)完成,那么應(yīng)該讓使用者能夠判斷他們要等待多久。

中止要求很簡(jiǎn)單。使用 Proxy 類別上可用的 Abort 方法,那是在您使用 [加入 Web 參考] 選項(xiàng)時(shí)建立的。關(guān)于中止要求,請(qǐng)記住幾件事。當(dāng)您呼叫 Abort 方法時(shí),任何未完成的要求仍然會(huì)完成,但它們完成時(shí)會(huì)有錯(cuò)誤。這表示,如果您使用回呼,則仍然會(huì)對(duì)每一個(gè)未完成的要求呼叫您的回呼函式。呼叫 EndInvoke 方法 (或是我們案例中的包裝函式 EndDelayedResponse) 時(shí),會(huì)產(chǎn)生錯(cuò)誤,指出基礎(chǔ)連接已關(guān)閉。

繁衍執(zhí)行緒以發(fā)出同步呼叫

還有另一個(gè)選項(xiàng)可用來(lái)解決異步呼叫的許多問題。那就是直接繁衍執(zhí)行緒,并讓該執(zhí)行緒發(fā)出容易撰寫程序代碼的同步呼叫。在某些案例中這是合理的,但您應(yīng)該了解關(guān)于此方式的一些議題。

首先,這會(huì)使 Web 服務(wù)呼叫程序代碼更簡(jiǎn)單,但也可能會(huì)需要實(shí)作與我們使用過(guò)的部份程序代碼一樣復(fù)雜的程序代碼,才能管理和在執(zhí)行緒之間通訊。如果您要發(fā)出很多個(gè) Web 服務(wù)呼叫,則您系統(tǒng)可能因?yàn)橛刑鄠(gè)執(zhí)行緒要管理而負(fù)擔(dān)過(guò)重。以正?蛻舳藨(yīng)用程序而言,這可能不是什么大不了的事,但如果您要從 ASP.NET 網(wǎng)頁(yè)發(fā)出呼叫,則您必須考慮有多少個(gè)使用者會(huì)同時(shí)使用您的系統(tǒng)。新增兩個(gè)執(zhí)行緒從 ASP.NET 網(wǎng)頁(yè)執(zhí)行 Web 服務(wù)呼叫,看起來(lái)負(fù)擔(dān)不大,但如果有 200 個(gè)人同時(shí)使用同一張網(wǎng)頁(yè)時(shí)會(huì)怎么樣?現(xiàn)在您談的是 400 個(gè)新執(zhí)行緒,那負(fù)擔(dān)一定很大。雖然執(zhí)行異步呼叫的回呼機(jī)制使用額外執(zhí)行緒來(lái)進(jìn)行回呼,但它們重復(fù)使用執(zhí)行緒集區(qū),以提高回呼效率—同時(shí)避免有數(shù)百個(gè)執(zhí)行緒同時(shí)執(zhí)行的問題。

如果繁衍背景執(zhí)行緒,使 Web 服務(wù)呼叫仍然在合理范圍內(nèi),那么您應(yīng)該考慮使用委派和處理執(zhí)行緒集區(qū)來(lái)繁衍這些執(zhí)行緒。然后您可以使用異步范例 (類似我們用于 Web 服務(wù)回呼的范例) 并發(fā)出函式呼叫來(lái)與執(zhí)行緒上的控件互動(dòng),藉此呼叫這些方法。有關(guān)使用委派發(fā)出一般異步方法呼叫的其它詳細(xì)信息,請(qǐng)參閱 Richard Grimes 的文章《.Net Delegates: Making Asynchronous Method Calls in the .Net Environment(英文)。

結(jié)論

異步發(fā)出 Web 服務(wù)呼叫,可能是透過(guò) HTTP .NET Framework 應(yīng)用程序使用 Web 服務(wù)的好點(diǎn)子。大部份真正的應(yīng)用程序會(huì)想要使用此功能來(lái)有效呼叫 Web 服務(wù),而不讓可能需要花費(fèi)長(zhǎng)時(shí)間的網(wǎng)絡(luò)呼叫,造成應(yīng)用程序被封鎖。.NET Framework 在支持透過(guò) HTTP 的異步 Web 服務(wù)呼叫的方式上很有彈性,它提供開發(fā)人員很多控制權(quán),來(lái)決定他們要如何處理呼叫的完成。
作者:Matt Pow… | 文章來(lái)源:Microsoft Corporation | 更新時(shí)間:2007-10-26 11:13:49

  • 上一篇文章:

  • 下一篇文章:

  • 相關(guān)文章:
    j2se 嵌入式腳本抓取引擎
    NET Framework 2.0 Service Pack 2下載地址
    解析.NET中的6各大的安全錯(cuò)誤
    .NET中Boolean,bool以及String,string之間的區(qū)別
    在VC 程序中自定義Vista事件日志
    .Net FrameWork 2.0 新增功能 Bulk Copy
    教程:.Net多線程和Windows Forms編程
    C++函數(shù)對(duì)象count_if
    語(yǔ)法C# 問關(guān)鍵字之:base、this
    C#中“+”的兩種功能
    軟件技術(shù)
    · 開發(fā)語(yǔ)言
    · Java技術(shù)
    · .Net技術(shù)
    · 數(shù)據(jù)庫(kù)開發(fā)
    最新文章  
    ·.net技術(shù) asp.net MVC3 Vi
    ·.net將視頻文件格式轉(zhuǎn)換成
    ·NET Framework 2.0 Servic
    ·如何動(dòng)態(tài)修改winform的app
    ·asp,net軟件結(jié)構(gòu)設(shè)計(jì)和相關(guān)
    ·學(xué)習(xí)怎樣使用ASP.NET中的虛
    ·,net基礎(chǔ)類的學(xué)習(xí):system
    ·.net學(xué)習(xí):c#事件的深入分
    ·Facade Pattern學(xué)習(xí)總結(jié)
    ·C#如何設(shè)置或者獲取目錄的
    ·如何使用XSL來(lái)定義ASP.NET
    ·理解WCF Data Contract契約
    ·如何能在.net2.0開發(fā)的控件
    ·模式怎樣使用,講解模式的
    ·如何解決Menu菜單被frame遮
    關(guān)于我們 | 軟件開發(fā) | 下載試用 | 客服中心 | 聯(lián)系我們 | 友情鏈接 | 網(wǎng)站地圖 | 新疆電子地圖 | RSS訂閱
    版權(quán)所有 © 2016 新疆二域軟件開發(fā)網(wǎng) m.jdtbank.com All Rights Reserved 新ICP備14003571號(hào)
    新疆軟件開發(fā)總機(jī):0991-4842803、4811639.
    客服QQ:596589785 ;地址:新疆烏魯木齊北京中路華聯(lián)大廈A-5C 郵編:830000
     
    新营市| 清河县| 淮阳县| 迭部县| 江华| 达州市| 仲巴县| 蕲春县| 卢氏县| 葫芦岛市| 清苑县| 兴文县| 香格里拉县| 黔南| 宁海县| 南漳县| 西畴县| 贡嘎县| 昌都县| 上饶县| 邹城市| 营山县| 封开县| 曲松县| 南乐县| 万安县| 额尔古纳市| 安福县| 延庆县| 水城县| 晋江市| 紫云| 建平县| 兴义市| 黔南| 汉沽区| 东平县| 微山县| 武定县| 海口市| 赫章县|