在第 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); ... } |
| 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); } } ... } |
| 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; } } |
Java Asp PHP .Net XML C/C++ CGI VB Jsp J2ee J2se J2me EJB Servlet Tomcat Resin Struts Weblogic Eclipse ANT GUI JMS Web servise IDEA Webphere Hibernate Spring Jboss Applet Swing Socket Javamail Perl Ajax P2P 安全 模式 框架 测试 开源 游戏
Windows XP Windows 2000 Windows 2003 Windows Me Windows 9.x Linux UNIX 注册表 操作系统 服务器 应用服务器