明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線(xiàn)學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

服務(wù)器端異步 Web 方法(一)

[摘要]摘要:Matt Powell 介紹了如何在服務(wù)器端使用異步 Web 方法,來(lái)創(chuàng)建高性能的 Microsoft ASP.NET Web 服務(wù)。 簡(jiǎn)介在九月份的第三篇專(zhuān)欄(英文)中,我談到了利用 Microsoft® .NET Framework 的客戶(hù)端功能通過(guò) HTTP 異步調(diào)用 ...
摘要:Matt Powell 介紹了如何在服務(wù)器端使用異步 Web 方法,來(lái)創(chuàng)建高性能的 Microsoft ASP.NET Web 服務(wù)。

簡(jiǎn)介

在九月份的第三篇專(zhuān)欄(英文)中,我談到了利用 Microsoft® .NET Framework 的客戶(hù)端功能通過(guò) HTTP 異步調(diào)用 Web 服務(wù)的問(wèn)題。這種調(diào)用 Web 服務(wù)的方法非常有用,使用時(shí)不必鎖定您的應(yīng)用程序或產(chǎn)生過(guò)多后臺(tái)線(xiàn)程,F(xiàn)在我們了解一下在服務(wù)器端提供類(lèi)似功能的異步 Web 方法。異步 Web 方法在編寫(xiě) ISAPI 擴(kuò)展方面具有與 HSE_STATUS_PENDING 方法類(lèi)似的高性能,但不需要為管理自己的線(xiàn)程池編寫(xiě)代碼,同時(shí)又具有以托管代碼方式運(yùn)行的所有優(yōu)點(diǎn)。

首先我們考慮一下常規(guī)的同步 Microsoft® ASP.NET Web 方法。當(dāng)您從同步 Web 方法返回時(shí),將發(fā)送對(duì)該方法的響應(yīng)。如果需要較長(zhǎng)的時(shí)間來(lái)完成請(qǐng)求,則處理請(qǐng)求的線(xiàn)程會(huì)一直被占用,直到方法調(diào)用結(jié)束。不幸的是,多數(shù)較長(zhǎng)的調(diào)用是由較長(zhǎng)的數(shù)據(jù)庫(kù)查詢(xún)或?qū)α硪粋(gè) Web 服務(wù)的調(diào)用等事件引起的。例如,如果您調(diào)用數(shù)據(jù)庫(kù),當(dāng)前線(xiàn)程會(huì)一直等待調(diào)用完成。線(xiàn)程無(wú)事可做,只是等待,直至聽(tīng)到查詢(xún)的返回。當(dāng)線(xiàn)程等待完成對(duì) TCP 套接字或后端 Web 服務(wù)的調(diào)用時(shí),也會(huì)出現(xiàn)類(lèi)似的問(wèn)題。

讓線(xiàn)程處于等待狀態(tài)很不好,特別是在服務(wù)器的運(yùn)行壓力很大的情況下。等待中的線(xiàn)程不會(huì)進(jìn)行任何有效工作,例如為其他請(qǐng)求提供服務(wù)。我們需要找到一種方法,能夠在服務(wù)器上開(kāi)始較長(zhǎng)的后臺(tái)進(jìn)程,同時(shí)又能將當(dāng)前線(xiàn)程返回到 ASP.NET 進(jìn)程池。然后,當(dāng)較長(zhǎng)的后臺(tái)進(jìn)程完成時(shí),我們調(diào)用一個(gè)回調(diào)函數(shù),結(jié)束對(duì)請(qǐng)求的處理,并通過(guò)某種方式通知 ASP.NET 請(qǐng)求已完成。實(shí)際上,這種功能可由 ASP.NET 使用異步 Web 方法提供。

異步 Web 方法的工作原理

當(dāng)您使用 Web 方法編寫(xiě)典型的 ASP.NET Web 服務(wù)時(shí),Microsoft® Visual Studio® .Net 只是編譯您的代碼以創(chuàng)建程序集;當(dāng)收到對(duì)其 Web 方法的請(qǐng)求時(shí),將調(diào)用該程序集。程序集本身并不知道關(guān)于 SOAP 的任何事情。因此,當(dāng)您的應(yīng)用程序首次啟動(dòng)時(shí),ASMX 處理程序必須反映您的程序集,以確定提供哪些 Web 方法。對(duì)于常規(guī)的同步請(qǐng)求,這些操作都很簡(jiǎn)單:找出哪些方法具有關(guān)聯(lián)的 WebMethod 屬性、基于 SOAPAction HTTP 標(biāo)頭來(lái)設(shè)置調(diào)用正確方法的邏輯。

對(duì)于異步請(qǐng)求,在反映過(guò)程中,ASMX 處理程序?qū)ふ揖哂心撤N簽名并將簽名識(shí)別為異步的 Web 方法。該處理程序?qū)ふ曳弦韵乱?guī)則的方法對(duì):

BeginXXX 和 EndXXX Web 方法,其中 XXX 是任意字符串,表示要提供的方法的名稱(chēng)。
BeginXXX 函數(shù)返回一個(gè) IAsyncResult 接口,并分別接受 AsyncCallback 和一個(gè)對(duì)象,作為其最后兩個(gè)輸入?yún)?shù)。
EndXXX 函數(shù)接受一個(gè) IAsyncResult 接口,作為其唯一的參數(shù)。
兩個(gè)方法都必須使用 WebMethod 屬性進(jìn)行標(biāo)識(shí)。
如果 ASMX 處理程序發(fā)現(xiàn)兩個(gè)方法符合上述所有條件,則將方法 XXX 作為常規(guī)的 Web 方法在其 WSDL 中提供。該方法將接受在 BeginXXX 的簽名中的 AsyncCallback 參數(shù)之前定義的參數(shù)作為輸入,并返回由 EndXXX 函數(shù)返回的內(nèi)容。因此,如果某個(gè) Web 方法具有如下同步聲明:

[WebMethod]

public string LengthyProcedure(int milliseconds) {...}

則異步聲明將為:

[WebMethod]

public IAsyncResult BeginLengthyProcedure(

int milliseconds,

AsyncCallback cb,

object s) {...}



[WebMethod]

public string EndLengthyProcedure(IAsyncResult call) {...}

每個(gè)方法的 WSDL 都是相同的。

在 ASMX 處理程序反映程序集并檢測(cè)到某個(gè)異步 Web 方法后,它必須以不同于處理同步請(qǐng)求的方式處理對(duì)該方法的請(qǐng)求。它將調(diào)用 BeginXXX 方法,而不是某個(gè)簡(jiǎn)單方法。它將傳入的請(qǐng)求還原序列化到要傳遞到函數(shù)的參數(shù)中(與處理同步請(qǐng)求時(shí)一樣);但是它還將指針傳遞到一個(gè)內(nèi)部回調(diào)函數(shù)(作為 BeginXXX 方法的額外 AsyncCallback 參數(shù))。

這種方法類(lèi)似于 .NET Framework 中 Web 服務(wù)客戶(hù)端應(yīng)用程序的異步編程模式。如果客戶(hù)端支持異步 Web 服務(wù)調(diào)用,則可以為客戶(hù)端計(jì)算機(jī)釋放占用的線(xiàn)程;如果服務(wù)器端支持異步 Web 服務(wù)調(diào)用,則可以釋放服務(wù)器計(jì)算機(jī)上占用的線(xiàn)程。但這里有兩個(gè)關(guān)鍵的區(qū)別。首先,不是由服務(wù)器代碼調(diào)用 BeginXXX 和 EndXXX 函數(shù),而是由 ASMX 處理程序調(diào)用。其次,您要為 BeginXXX 和 EndXXX 函數(shù)編寫(xiě)代碼,而不能使用由 WSDL.EXE 或 Visual Studio .NET 中的 Add Web Reference(添加 Web 引用)向?qū)傻拇a。但結(jié)果是相同的,即釋放線(xiàn)程以使其能夠執(zhí)行其他進(jìn)程。

ASMX 處理程序調(diào)用服務(wù)器的 BeginXXX 函數(shù)后,會(huì)將線(xiàn)程返回到進(jìn)程線(xiàn)程池,使之能夠處理接收到的任何其他請(qǐng)求。但是,還不能釋放請(qǐng)求的 HttpContext。ASMX 處理程序?qū)⒌却,直到它傳遞給 BeginXXX 函數(shù)的回調(diào)函數(shù)被調(diào)用,它才結(jié)束處理請(qǐng)求。

一旦回調(diào)函數(shù)被調(diào)用,ASMX 處理程序?qū)⒄{(diào)用 EndXXX 函數(shù),使您的 Web 方法可以完成任何所要執(zhí)行的處理,并且可以得到被序列化到 SOAP 響應(yīng)中的返回?cái)?shù)據(jù)。EndXXX 函數(shù)返回后將發(fā)送響應(yīng),只有此時(shí)該請(qǐng)求的 HttpContext 才得到釋放。