ASP.NET2.0中數(shù)據(jù)源控件之異步數(shù)據(jù)訪問
更新時間:2006年09月28日 00:00:00 作者:
在第 1 部分和第 2 部分中,建立了 WeatherDataSource 控件,該控件針對 weather.com(英文)所提供的 XML API 來運(yùn)行,使用 WebRequest 和 WebResponse 來通過 HTTP 訪問數(shù)據(jù)。迄今為止,均是同步訪問該服務(wù)。因此,頁面處理被阻止,直到 Web 請求完成為止。此方法對于測試頁面是有效的,在小站點(diǎn)上也可能有效,但是在接收大量通信流量的站點(diǎn)上則會慘??;例如門戶頁面,天氣模塊在其中可能非常常見。
引言
在線程池中有固定不變的大量線程可用于服務(wù)請求,遺憾的是,該解決方案并非僅僅提高限制(還會增加線程占用資源以及 CPU 占用資源)。因此,當(dāng)一個頁面被阻止而等候另一個服務(wù)器時,它還在占用線程,因而可能會導(dǎo)致其他傳入的請求在隊(duì)列中等候更長的時間。這將導(dǎo)致對站點(diǎn)的訪問變慢,并降低 CPU 的利用率。在 Visual Studio 2005 中,我們引入了異步頁面,這使得控件能夠定義它們希望異步完成的任務(wù),即,無需阻止用來處理請求的線程。在此將不介紹異步頁面本身的詳細(xì)信息,Dmitry(英文)和 Fritz Onion(英文)中以前已經(jīng)有所介紹。此處要介紹的是如何在數(shù)據(jù)源控件中利用此功能,使用加載項(xiàng)框架來實(shí)現(xiàn)異步數(shù)據(jù)源。
背景
在第 1 部分中,間接提到了 DataSourceView 類的有些古怪的設(shè)計(jì):
您會注意到,公共 Select 方法實(shí)際上并不返回任何數(shù)據(jù)。而是接受一個回?fù)埽⑼ㄟ^該回?fù)軄矸祷財(cái)?shù)據(jù)。它只調(diào)用受保護(hù)的 ExecuteSelect(它始終執(zhí)行同步數(shù)據(jù)訪問)來檢索要退還給數(shù)據(jù)綁定控件的數(shù)據(jù)。DataSourceView 類的默認(rèn)實(shí)現(xiàn)實(shí)際上不會異步執(zhí)行任何操作。原因在于,并不存在任何現(xiàn)成的異步數(shù)據(jù)源控件。但 OM 的設(shè)計(jì)確實(shí)允許實(shí)現(xiàn)異步數(shù)據(jù)訪問,在這種設(shè)計(jì)下,數(shù)據(jù)在異步工作完成之后才可用。因此,我們就有了一個基于回?fù)艿哪P汀?br>
那些熟悉框架中的異步 API 的人會注意到缺少了異步模式:公共 Select、BeginSelect 和 EndSelect 方法,在這些方法中,數(shù)據(jù)綁定控件選擇要調(diào)用哪些方法。但是,數(shù)據(jù)綁定控件并不能確定是選擇同步 API 還是選擇異步 API。此外,在數(shù)據(jù)綁定控件上添加屬性也毫無作用。數(shù)據(jù)源控件封裝了有關(guān)如何訪問數(shù)據(jù)存儲的詳細(xì)信息,對數(shù)據(jù)存儲的訪問是同步發(fā)生還是異步發(fā)生應(yīng)該根據(jù)數(shù)據(jù)源是否基于語義來決定或者根據(jù)自定義屬性來決定。潛在的“bool PerformAsyncDataAccess”屬性的正確位置適合于數(shù)據(jù)源控件本身。這還使得數(shù)據(jù)源控件可以使用一種方法來執(zhí)行數(shù)據(jù)訪問,即使多個數(shù)據(jù)綁定控件被綁定到同一個數(shù)據(jù)源。至此已多次解釋了該體系結(jié)構(gòu)所蘊(yùn)涵的這些微妙的概念,但愿能闡明該設(shè)計(jì)。
關(guān)于異步任務(wù),最后要注意的一點(diǎn)是:頁面是否應(yīng)該執(zhí)行任何異步工作完全由頁面開發(fā)人員最終決定(通過 Page 指令的 Async 屬性)。因此,任何編寫良好的數(shù)據(jù)源控件必須退化為根據(jù)需要來執(zhí)行同步數(shù)據(jù)訪問。
框架
在此框架中(在此系列結(jié)尾會用示例的剩余部分來演示這一點(diǎn)),已將 AsyncDataSource 和 AsyncDataSourceView 基類放在一起,這些基類可以用于實(shí)現(xiàn)能夠執(zhí)行異步數(shù)據(jù)訪問的數(shù)據(jù)源控件。以下大概介紹了框架內(nèi)容,以及有助于弄清楚其含義的一些注釋:
示例
現(xiàn)在,新的 AsyncWeatherDataSource 將從 AsyncDataSourceControl 中派生,而 AsyncWeatherDataSourceView 將從 AsyncDataSourceView 中派生。
要注意的關(guān)鍵問題是,在使用該框架時,只需要實(shí)現(xiàn) BeginExecuteSelect 和 EndExecuteSelect。在它們的實(shí)現(xiàn)過程中,通常要調(diào)用由該框架中的各種對象(例如 WebRequest 或 IO 流)所揭示的 BeginXXX 和 EndXXX 方法(在 Visual Studio 2005 中,還需要調(diào)用 SqlDataCommand),并返回 IAsyncResult。在此示例中,有一個封裝了基礎(chǔ) WebRequest 對象的 WeatherService 幫助程序類。
對于那些實(shí)際缺少異步模式的框架,您在此會看到有效的異步模式;以及您要實(shí)現(xiàn)的 BeginExecuteSelect 和 EndExecuteSelect,和您要調(diào)用以返回 IAsyncResult 實(shí)例的 Begin 和 End 方法。
最有趣的可能是 SynchronousAsyncSelectResult 類(在某種程度上而言是一種矛盾)。此類是框架附帶的。它基本上是一個 IAsyncResult 實(shí)現(xiàn),可使數(shù)據(jù)立即可用,并從其 IAsyncResult.CompletedSynchronously 屬性報(bào)告 true。到目前為止,這僅適用于未選擇郵政編碼的情況,并且需要返回 null(啟動異步任務(wù)而只返回 null 是沒有意義的),但正如您會在下文中看到的,這在其他方案中也是有用的。
頁面基礎(chǔ)結(jié)構(gòu)隱藏了在 Microsoft ASP.NET 上下文中執(zhí)行異步工作的大部分詳細(xì)信息。希望在此提供的框架使您執(zhí)行最少的操作就能編寫使用此基礎(chǔ)結(jié)構(gòu)的數(shù)據(jù)源。不過,就其本質(zhì)而言,實(shí)現(xiàn)異步行為是復(fù)雜的。有時候,第一次閱讀本文時會有一些疑問,而第二次閱讀時可能就明白了。您可以使用下面“我的評論”表單來發(fā)送問題或進(jìn)行討論。
引言
在線程池中有固定不變的大量線程可用于服務(wù)請求,遺憾的是,該解決方案并非僅僅提高限制(還會增加線程占用資源以及 CPU 占用資源)。因此,當(dāng)一個頁面被阻止而等候另一個服務(wù)器時,它還在占用線程,因而可能會導(dǎo)致其他傳入的請求在隊(duì)列中等候更長的時間。這將導(dǎo)致對站點(diǎn)的訪問變慢,并降低 CPU 的利用率。在 Visual Studio 2005 中,我們引入了異步頁面,這使得控件能夠定義它們希望異步完成的任務(wù),即,無需阻止用來處理請求的線程。在此將不介紹異步頁面本身的詳細(xì)信息,Dmitry(英文)和 Fritz Onion(英文)中以前已經(jīng)有所介紹。此處要介紹的是如何在數(shù)據(jù)源控件中利用此功能,使用加載項(xiàng)框架來實(shí)現(xiàn)異步數(shù)據(jù)源。
背景
在第 1 部分中,間接提到了 DataSourceView 類的有些古怪的設(shè)計(jì):
public abstract class DataSourceView { public virtual void Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback); protected abstract IEnumerable ExecuteSelect( DataSourceSelectArguments arguments); ... } |
您會注意到,公共 Select 方法實(shí)際上并不返回任何數(shù)據(jù)。而是接受一個回?fù)埽⑼ㄟ^該回?fù)軄矸祷財(cái)?shù)據(jù)。它只調(diào)用受保護(hù)的 ExecuteSelect(它始終執(zhí)行同步數(shù)據(jù)訪問)來檢索要退還給數(shù)據(jù)綁定控件的數(shù)據(jù)。DataSourceView 類的默認(rèn)實(shí)現(xiàn)實(shí)際上不會異步執(zhí)行任何操作。原因在于,并不存在任何現(xiàn)成的異步數(shù)據(jù)源控件。但 OM 的設(shè)計(jì)確實(shí)允許實(shí)現(xiàn)異步數(shù)據(jù)訪問,在這種設(shè)計(jì)下,數(shù)據(jù)在異步工作完成之后才可用。因此,我們就有了一個基于回?fù)艿哪P汀?br>
那些熟悉框架中的異步 API 的人會注意到缺少了異步模式:公共 Select、BeginSelect 和 EndSelect 方法,在這些方法中,數(shù)據(jù)綁定控件選擇要調(diào)用哪些方法。但是,數(shù)據(jù)綁定控件并不能確定是選擇同步 API 還是選擇異步 API。此外,在數(shù)據(jù)綁定控件上添加屬性也毫無作用。數(shù)據(jù)源控件封裝了有關(guān)如何訪問數(shù)據(jù)存儲的詳細(xì)信息,對數(shù)據(jù)存儲的訪問是同步發(fā)生還是異步發(fā)生應(yīng)該根據(jù)數(shù)據(jù)源是否基于語義來決定或者根據(jù)自定義屬性來決定。潛在的“bool PerformAsyncDataAccess”屬性的正確位置適合于數(shù)據(jù)源控件本身。這還使得數(shù)據(jù)源控件可以使用一種方法來執(zhí)行數(shù)據(jù)訪問,即使多個數(shù)據(jù)綁定控件被綁定到同一個數(shù)據(jù)源。至此已多次解釋了該體系結(jié)構(gòu)所蘊(yùn)涵的這些微妙的概念,但愿能闡明該設(shè)計(jì)。
關(guān)于異步任務(wù),最后要注意的一點(diǎn)是:頁面是否應(yīng)該執(zhí)行任何異步工作完全由頁面開發(fā)人員最終決定(通過 Page 指令的 Async 屬性)。因此,任何編寫良好的數(shù)據(jù)源控件必須退化為根據(jù)需要來執(zhí)行同步數(shù)據(jù)訪問。
框架
在此框架中(在此系列結(jié)尾會用示例的剩余部分來演示這一點(diǎn)),已將 AsyncDataSource 和 AsyncDataSourceView 基類放在一起,這些基類可以用于實(shí)現(xiàn)能夠執(zhí)行異步數(shù)據(jù)訪問的數(shù)據(jù)源控件。以下大概介紹了框架內(nèi)容,以及有助于弄清楚其含義的一些注釋:
public abstract class AsyncDataSourceControl : DataSourceControl, IAsyncDataSource { private bool _performAsyncDataAccess; protected AsyncDataSourceControl() { _performAsyncDataAccess = true; } public virtual bool PerformAsyncDataAccess { get; set; } bool IAsyncDataSource.IsAsync { get { return _performAsyncDataAccess && Page.IsAsync; } } } public abstract class AsyncDataSourceView : DataSourceView { protected abstract IAsyncResult BeginExecuteSelect( DataSourceSelectArguments arguments, AsyncCallback asyncCallback, object asyncState); protected abstract IEnumerable EndExecuteSelect( IAsyncResult asyncResult); protected override IEnumerable ExecuteSelect( DataSourceSelectArguments arguments) { //實(shí)現(xiàn)從 DataSourceView 中繼承的 //抽象 ExecuteSelect 方法, //方法是使用 BeginExecuteSelect 和 EndExecuteSelect, //以便通過阻止來 //進(jìn)行同步數(shù)據(jù)訪問。 } private IAsyncResult OnBeginSelect(object sender, EventArgs e, AsyncCallback asyncCallback, object extraData); private void OnEndSelect(IAsyncResult asyncResult); public override void Select(DataSourceSelectArguments arguments, DataSourceViewSelectCallback callback) { if (_owner.IsAsync) { //使用 OnBeginSelect 和 OnEndSelect //作為 BeginEventHandler 和 EndEventHandler 方法, //來調(diào)用 Page.RegisterAsyncTask, //以指明需要 //進(jìn)行異步工作。這些方法將依次 //調(diào)用特定的 //數(shù)據(jù)源實(shí)現(xiàn),方法是調(diào)用 //已在此類中引入的 //抽象 BeginExecuteSelect 和 EndExecuteSelect //方法。 } else { //執(zhí)行同步數(shù)據(jù)訪問 base.Select(arguments, callback); } } ... } |
示例
現(xiàn)在,新的 AsyncWeatherDataSource 將從 AsyncDataSourceControl 中派生,而 AsyncWeatherDataSourceView 將從 AsyncDataSourceView 中派生。
public class AsyncWeatherDataSource : AsyncDataSourceControl { //與 WeatherDataSource 相同 } private sealed class AsyncWeatherDataSourceView : AsyncDataSourceView { private AsyncWeatherDataSource _owner; private WeatherService _weatherService; public AsyncWeatherDataSourceView(AsyncWeatherDataSource owner, string viewName) : base(owner, viewName) { _owner = owner; } protected override IAsyncResult BeginExecuteSelect(DataSourceSelectArguments arguments, AsyncCallback asyncCallback, object asyncState) { arguments.RaiseUnsupportedCapabilitiesError(this); string zipCode = _owner.GetSelectedZipCode(); if (zipCode.Length == 0) { return new SynchronousAsyncSelectResult(/* selectResult */ null, asyncCallback, asyncState); } _weatherService = new WeatherService(zipCode); return _weatherService.BeginGetWeather(asyncCallback, asyncState); } protected override IEnumerable EndExecuteSelect(IAsyncResult asyncResult) { SynchronousAsyncSelectResult syncResult = asyncResult as SynchronousAsyncSelectResult; if (syncResult != null) { return syncResult.SelectResult; } else { Weather weatherObject = _weatherService.EndGetWeather(asyncResult); _weatherService = null; if (weatherObject != null) { return new Weather[] { weatherObject }; } } return null; } } |
要注意的關(guān)鍵問題是,在使用該框架時,只需要實(shí)現(xiàn) BeginExecuteSelect 和 EndExecuteSelect。在它們的實(shí)現(xiàn)過程中,通常要調(diào)用由該框架中的各種對象(例如 WebRequest 或 IO 流)所揭示的 BeginXXX 和 EndXXX 方法(在 Visual Studio 2005 中,還需要調(diào)用 SqlDataCommand),并返回 IAsyncResult。在此示例中,有一個封裝了基礎(chǔ) WebRequest 對象的 WeatherService 幫助程序類。
對于那些實(shí)際缺少異步模式的框架,您在此會看到有效的異步模式;以及您要實(shí)現(xiàn)的 BeginExecuteSelect 和 EndExecuteSelect,和您要調(diào)用以返回 IAsyncResult 實(shí)例的 Begin 和 End 方法。
最有趣的可能是 SynchronousAsyncSelectResult 類(在某種程度上而言是一種矛盾)。此類是框架附帶的。它基本上是一個 IAsyncResult 實(shí)現(xiàn),可使數(shù)據(jù)立即可用,并從其 IAsyncResult.CompletedSynchronously 屬性報(bào)告 true。到目前為止,這僅適用于未選擇郵政編碼的情況,并且需要返回 null(啟動異步任務(wù)而只返回 null 是沒有意義的),但正如您會在下文中看到的,這在其他方案中也是有用的。
頁面基礎(chǔ)結(jié)構(gòu)隱藏了在 Microsoft ASP.NET 上下文中執(zhí)行異步工作的大部分詳細(xì)信息。希望在此提供的框架使您執(zhí)行最少的操作就能編寫使用此基礎(chǔ)結(jié)構(gòu)的數(shù)據(jù)源。不過,就其本質(zhì)而言,實(shí)現(xiàn)異步行為是復(fù)雜的。有時候,第一次閱讀本文時會有一些疑問,而第二次閱讀時可能就明白了。您可以使用下面“我的評論”表單來發(fā)送問題或進(jìn)行討論。
您可能感興趣的文章:
- asp.net+ajaxfileupload.js 實(shí)現(xiàn)文件異步上傳代碼分享
- asp.net 使用js分頁實(shí)現(xiàn)異步加載數(shù)據(jù)
- asp.net jquery+ajax異步刷新實(shí)現(xiàn)示例
- ASP.NET之自定義異步HTTP處理程序(圖文教程)
- jquery異步調(diào)用頁面后臺方法‏(asp.net)
- JQuery FlexiGrid的asp.net完美解決方案 dotNetFlexGrid-.Net原生的異步表格控件
- javascript 異步頁面查詢實(shí)現(xiàn)代碼(asp.net)
- asp.net下實(shí)現(xiàn)支持文件分塊多點(diǎn)異步上傳的 Web Services
- asp.net實(shí)現(xiàn)數(shù)據(jù)從DataTable導(dǎo)入到Excel文件并創(chuàng)建表的方法
- ASP.NET DataTable去掉重復(fù)行的2種方法
- ASP.NET中DataTable與DataSet之間的轉(zhuǎn)換示例
- ASP.NET怎么操作DataTable實(shí)例應(yīng)用
- asp.net 讀取Excel數(shù)據(jù)到DataTable的代碼
- asp.net異步獲取datatable并顯示的實(shí)現(xiàn)方法
相關(guān)文章
asp.net表單提交時防重復(fù)提交并執(zhí)行前臺的JS驗(yàn)證
今天遇到這樣的一個情況,就是用戶重復(fù)提交。當(dāng)然這個不能怪用戶,只能怪.NET或者服務(wù)器反應(yīng)遲鈍,下面有個不錯的教程,大家可以參考下2013-10-10asp.net實(shí)現(xiàn)將ppt文檔轉(zhuǎn)換成pdf的方法
這篇文章主要介紹了asp.net實(shí)現(xiàn)將ppt文檔轉(zhuǎn)換成pdf的方法,通過自定義函數(shù)實(shí)現(xiàn)將pptx格式的文件轉(zhuǎn)換成pdf格式文件的功能,是非常實(shí)用的技巧,需要的朋友可以參考下2014-11-11Visual Studio 2017下ASP.NET CORE的TagHelper智能提示解決辦法
這篇文章主要為大家詳細(xì)介紹了Visual Studio 2017下ASP.NET CORE TagHelper智能提示的解決辦法,具有一定的參考價值,感興趣的小伙伴們可以參考一下2017-03-03asp.net core利用AccessControlHelper實(shí)現(xiàn)控制訪問權(quán)限
這篇文章主要給大家介紹了關(guān)于asp.net core利用AccessControlHelper實(shí)現(xiàn)控制訪問權(quán)限的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者使用asp.net core具有一定的參考學(xué)習(xí)價值,需要的朋友們下面來一起學(xué)習(xí)學(xué)習(xí)吧2019-10-10關(guān)于前臺調(diào)用后臺事件__doPostBack函數(shù)
關(guān)于前臺調(diào)用后臺事件__doPostBack函數(shù)...2007-04-04關(guān)于服務(wù)器或虛擬主機(jī)不支持 AjaxPro 的問題終極解決方法
asp.net的網(wǎng)站,訪問時提示不支持 AjaxPro,那就因?yàn)檎`刪的映射導(dǎo)致,可以通過下面的方法解決2012-03-03C#中實(shí)現(xiàn)偽靜態(tài)頁面兩種方式介紹
偽靜態(tài)技術(shù)的誕生,帶動了于搜索引擎友好C#中實(shí)現(xiàn)偽靜態(tài)頁面有兩種方式,本文將一一詳解,感興趣的朋友可以參考下,希望本文對你學(xué)習(xí)偽靜態(tài)有所幫助2013-01-01