分享
 
 
 

ASP.NET2.0中数据源控件之异步数据访问

王朝asp·作者佚名  2008-05-21
窄屏简体版  字體: |||超大  

在第 1 部分和第 2 部分中,建立了 WeatherDataSource 控件,该控件针对 weather.com(英文)所提供的 XML API 来运行,使用 WebRequest 和 WebResponse 来通过 HTTP 访问数据。迄今为止,均是同步访问该服务。因此,页面处理被阻止,直到 Web 请求完成为止。此方法对于测试页面是有效的,在小站点上也可能有效,但是在接收大量通信流量的站点上则会惨败;例如门户页面,天气模块在其中可能非常常见。

引言

在线程池中有固定不变的大量线程可用于服务请求,遗憾的是,该解决方案并非仅仅提高限制(还会增加线程占用资源以及 CPU 占用资源)。因此,当一个页面被阻止而等候另一个服务器时,它还在占用线程,因而可能会导致其他传入的请求在队列中等候更长的时间。这将导致对站点的访问变慢,并降低 CPU 的利用率。在 Visual Studio 2005 中,我们引入了异步页面,这使得控件能够定义它们希望异步完成的任务,即,无需阻止用来处理请求的线程。在此将不介绍异步页面本身的详细信息,Dmitry(英文)和 Fritz Onion(英文)中以前已经有所介绍。此处要介绍的是如何在数据源控件中利用此功能,使用加载项框架来实现异步数据源。

背景

在第 1 部分中,间接提到了 DataSourceView 类的有些古怪的设计:

public abstract class DataSourceView {

public virtual void Select(DataSourceSelectArguments arguments,

DataSourceViewSelectCallback callback);

protected abstract IEnumerable ExecuteSelect(

DataSourceSelectArguments arguments);

...}

您会注意到,公共 Select 方法实际上并不返回任何数据。而是接受一个回拨,并通过该回拨来返回数据。它只调用受保护的 ExecuteSelect(它始终执行同步数据访问)来检索要退还给数据绑定控件的数据。DataSourceView 类的默认实现实际上不会异步执行任何操作。原因在于,并不存在任何现成的异步数据源控件。但 OM 的设计确实允许实现异步数据访问,在这种设计下,数据在异步工作完成之后才可用。因此,我们就有了一个基于回拨的模型。

那些熟悉框架中的异步 API 的人会注意到缺少了异步模式:公共 Select、BeginSelect 和 EndSelect 方法,在这些方法中,数据绑定控件选择要调用哪些方法。但是,数据绑定控件并不能确定是选择同步 API 还是选择异步 API。此外,在数据绑定控件上添加属性也毫无作用。数据源控件封装了有关如何访问数据存储的详细信息,对数据存储的访问是同步发生还是异步发生应该根据数据源是否基于语义来决定或者根据自定义属性来决定。潜在的“bool PerformAsyncDataAccess”属性的正确位置适合于数据源控件本身。这还使得数据源控件可以使用一种方法来执行数据访问,即使多个数据绑定控件被绑定到同一个数据源。至此已多次解释了该体系结构所蕴涵的这些微妙的概念,但愿能阐明该设计。

关于异步任务,最后要注意的一点是:页面是否应该执行任何异步工作完全由页面开发人员最终决定(通过 Page 指令的 Async 属性)。因此,任何编写良好的数据源控件必须退化为根据需要来执行同步数据访问。

框架

在此框架中(在此系列结尾会用示例的剩余部分来演示这一点),已将 AsyncDataSource 和 AsyncDataSourceView 基类放在一起,这些基类可以用于实现能够执行异步数据访问的数据源控件。以下大概介绍了框架内容,以及有助于弄清楚其含义的一些注释:

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) {

//实现从 DataSourceView 中继承的

//抽象 ExecuteSelect 方法,

//方法是使用 BeginExecuteSelect 和 EndExecuteSelect,

//以便通过阻止来

//进行同步数据访问。

}

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 方法,

//来调用 Page.RegisterAsyncTask,

//以指明需要

//进行异步工作。这些方法将依次

//调用特定的

//数据源实现,方法是调用

//已在此类中引入的

//抽象 BeginExecuteSelect 和 EndExecuteSelect

//方法。

}

else {

//执行同步数据访问

base.Select(arguments, callback);

}

}

...}

示例

现在,新的 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;}}

要注意的关键问题是,在使用该框架时,只需要实现 BeginExecuteSelect 和 EndExecuteSelect。在它们的实现过程中,通常要调用由该框架中的各种对象(例如 WebRequest 或 IO 流)所揭示的 BeginXXX 和 EndXXX 方法(在 Visual Studio 2005 中,还需要调用 SqlDataCommand),并返回 IAsyncResult。在此示例中,有一个封装了基础 WebRequest 对象的 WeatherService 帮助程序类。

对于那些实际缺少异步模式的框架,您在此会看到有效的异步模式;以及您要实现的 BeginExecuteSelect 和 EndExecuteSelect,和您要调用以返回 IAsyncResult 实例的 Begin 和 End 方法。

最有趣的可能是 SynchronousAsyncSelectResult 类(在某种程度上而言是一种矛盾)。此类是框架附带的。它基本上是一个 IAsyncResult 实现,可使数据立即可用,并从其 IAsyncResult.CompletedSynchronously 属性报告 true。到目前为止,这仅适用于未选择邮政编码的情况,并且需要返回 null(启动异步任务而只返回 null 是没有意义的),但正如您会在下文中看到的,这在其他方案中也是有用的。

页面基础结构隐藏了在 Microsoft ASP.NET 上下文中执行异步工作的大部分详细信息。希望在此提供的框架使您执行最少的操作就能编写使用此基础结构的数据源。不过,就其本质而言,实现异步行为是复杂的。有时候,第一次阅读本文时会有一些疑问,而第二次阅读时可能就明白了。您可以使用下面“我的评论”表单来发送问题或进行讨论。

 
 
 
免责声明:本文为网络用户发布,其观点仅代表作者个人观点,与本站无关,本站仅提供信息存储服务。文中陈述内容未经本站证实,其真实性、完整性、及时性本站不作任何保证或承诺,请读者仅作参考,并请自行核实相关内容。
2023年上半年GDP全球前十五强
 百态   2023-10-24
美众议院议长启动对拜登的弹劾调查
 百态   2023-09-13
上海、济南、武汉等多地出现不明坠落物
 探索   2023-09-06
印度或要将国名改为“巴拉特”
 百态   2023-09-06
男子为女友送行,买票不登机被捕
 百态   2023-08-20
手机地震预警功能怎么开?
 干货   2023-08-06
女子4年卖2套房花700多万做美容:不但没变美脸,面部还出现变形
 百态   2023-08-04
住户一楼被水淹 还冲来8头猪
 百态   2023-07-31
女子体内爬出大量瓜子状活虫
 百态   2023-07-25
地球连续35年收到神秘规律性信号,网友:不要回答!
 探索   2023-07-21
全球镓价格本周大涨27%
 探索   2023-07-09
钱都流向了那些不缺钱的人,苦都留给了能吃苦的人
 探索   2023-07-02
倩女手游刀客魅者强控制(强混乱强眩晕强睡眠)和对应控制抗性的关系
 百态   2020-08-20
美国5月9日最新疫情:美国确诊人数突破131万
 百态   2020-05-09
荷兰政府宣布将集体辞职
 干货   2020-04-30
倩女幽魂手游师徒任务情义春秋猜成语答案逍遥观:鹏程万里
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案神机营:射石饮羽
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案昆仑山:拔刀相助
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案天工阁:鬼斧神工
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案丝路古道:单枪匹马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:与虎谋皮
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:李代桃僵
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案镇郊荒野:指鹿为马
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:小鸟依人
 干货   2019-11-12
倩女幽魂手游师徒任务情义春秋猜成语答案金陵:千金买邻
 干货   2019-11-12
 
推荐阅读
 
 
 
>>返回首頁<<
 
靜靜地坐在廢墟上,四周的荒凉一望無際,忽然覺得,淒涼也很美
© 2005- 王朝網路 版權所有