色尼玛亚洲综合影院,亚洲3atv精品一区二区三区,麻豆freexxxx性91精品,欧美在线91

ASP.NET2.0中數(shù)據(jù)源控件之異步數(shù)據(jù)訪問

  在第 1 部分和第 2 部分中,建立了 WeatherDataSource 控件,該控件針對 weather.com(英文)所提供的 XML API 來運行,使用 WebRequest 和 WebResponse 來通過 HTTP 訪問數(shù)據(jù)。迄今為止,均是同步訪問該服務(wù)。因此,頁面處理被阻止,直到 Web 請求完成為止。此方法對于測試頁面是有效的,在小站點上也可能有效,但是在接收大量通信流量的站點上則會慘??;例如門戶頁面,天氣模塊在其中可能非常常見。

  引言

  在線程池中有固定不變的大量線程可用于服務(wù)請求,遺憾的是,該解決方案并非僅僅提高限制(還會增加線程占用資源以及 CPU 占用資源)。因此,當一個頁面被阻止而等候另一個服務(wù)器時,它還在占用線程,因而可能會導(dǎo)致其他傳入的請求在隊列中等候更長的時間。這將導(dǎo)致對站點的訪問變慢,并降低 CPU 的利用率。在 Visual Studio 2005 中,我們引入了異步頁面,這使得控件能夠定義它們希望異步完成的任務(wù),即,無需阻止用來處理請求的線程。在此將不介紹異步頁面本身的詳細信息,Dmitry(英文)和 Fritz Onion(英文)中以前已經(jīng)有所介紹。此處要介紹的是如何在數(shù)據(jù)源控件中利用此功能,使用加載項框架來實現(xiàn)異步數(shù)據(jù)源。

  背景

  在第 1 部分中,間接提到了 DataSourceView 類的有些古怪的設(shè)計:

public abstract class DataSourceView {
 public virtual void Select(DataSourceSelectArguments arguments,
  DataSourceViewSelectCallback callback);
 protected abstract IEnumerable ExecuteSelect(
  DataSourceSelectArguments arguments);
 ...
}

  您會注意到,公共 Select 方法實際上并不返回任何數(shù)據(jù)。而是接受一個回撥,并通過該回撥來返回數(shù)據(jù)。它只調(diào)用受保護的 ExecuteSelect(它始終執(zhí)行同步數(shù)據(jù)訪問)來檢索要退還給數(shù)據(jù)綁定控件的數(shù)據(jù)。DataSourceView 類的默認實現(xiàn)實際上不會異步執(zhí)行任何操作。原因在于,并不存在任何現(xiàn)成的異步數(shù)據(jù)源控件。但 OM 的設(shè)計確實允許實現(xiàn)異步數(shù)據(jù)訪問,在這種設(shè)計下,數(shù)據(jù)在異步工作完成之后才可用。因此,我們就有了一個基于回撥的模型。

  那些熟悉框架中的異步 API 的人會注意到缺少了異步模式:公共 Select、BeginSelect 和 EndSelect 方法,在這些方法中,數(shù)據(jù)綁定控件選擇要調(diào)用哪些方法。但是,數(shù)據(jù)綁定控件并不能確定是選擇同步 API 還是選擇異步 API。此外,在數(shù)據(jù)綁定控件上添加屬性也毫無作用。數(shù)據(jù)源控件封裝了有關(guān)如何訪問數(shù)據(jù)存儲的詳細信息,對數(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)所蘊涵的這些微妙的概念,但愿能闡明該設(shè)計。

  關(guān)于異步任務(wù),最后要注意的一點是:頁面是否應(yīng)該執(zhí)行任何異步工作完全由頁面開發(fā)人員最終決定(通過 Page 指令的 Async 屬性)。因此,任何編寫良好的數(shù)據(jù)源控件必須退化為根據(jù)需要來執(zhí)行同步數(shù)據(jù)訪問。

  框架

  在此框架中(在此系列結(jié)尾會用示例的剩余部分來演示這一點),已將 AsyncDataSource 和 AsyncDataSourceView 基類放在一起,這些基類可以用于實現(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) {
    //實現(xiàn)從 DataSourceView 中繼承的
    //抽象 ExecuteSelect 方法,
    //方法是使用 BeginExecuteSelect 和 EndExecuteSelect,
    //以便通過阻止來
    //進行同步數(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,
      //以指明需要
      //進行異步工作。這些方法將依次
      //調(diào)用特定的
      //數(shù)據(jù)源實現(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)鍵問題是,在使用該框架時,只需要實現(xiàn) BeginExecuteSelect 和 EndExecuteSelect。在它們的實現(xiàn)過程中,通常要調(diào)用由該框架中的各種對象(例如 WebRequest 或 IO 流)所揭示的 BeginXXX 和 EndXXX 方法(在 Visual Studio 2005 中,還需要調(diào)用 SqlDataCommand),并返回 IAsyncResult。在此示例中,有一個封裝了基礎(chǔ) WebRequest 對象的 WeatherService 幫助程序類。

  對于那些實際缺少異步模式的框架,您在此會看到有效的異步模式;以及您要實現(xiàn)的 BeginExecuteSelect 和 EndExecuteSelect,和您要調(diào)用以返回 IAsyncResult 實例的 Begin 和 End 方法。

  最有趣的可能是 SynchronousAsyncSelectResult 類(在某種程度上而言是一種矛盾)。此類是框架附帶的。它基本上是一個 IAsyncResult 實現(xiàn),可使數(shù)據(jù)立即可用,并從其 IAsyncResult.CompletedSynchronously 屬性報告 true。到目前為止,這僅適用于未選擇郵政編碼的情況,并且需要返回 null(啟動異步任務(wù)而只返回 null 是沒有意義的),但正如您會在下文中看到的,這在其他方案中也是有用的。

  頁面基礎(chǔ)結(jié)構(gòu)隱藏了在 Microsoft ASP.NET 上下文中執(zhí)行異步工作的大部分詳細信息。希望在此提供的框架使您執(zhí)行最少的操作就能編寫使用此基礎(chǔ)結(jié)構(gòu)的數(shù)據(jù)源。不過,就其本質(zhì)而言,實現(xiàn)異步行為是復(fù)雜的。有時候,第一次閱讀本文時會有一些疑問,而第二次閱讀時可能就明白了。您可以使用下面“我的評論”表單來發(fā)送問題或進行討論。

AspNet技術(shù)ASP.NET2.0中數(shù)據(jù)源控件之異步數(shù)據(jù)訪問,轉(zhuǎn)載需保留來源!

鄭重聲明:本文版權(quán)歸原作者所有,轉(zhuǎn)載文章僅為傳播更多信息之目的,如作者信息標記有誤,請第一時間聯(lián)系我們修改或刪除,多謝。

主站蜘蛛池模板: 平和县| 宝山区| 合江县| 夏河县| 邯郸县| 清徐县| 修武县| 沾益县| 丘北县| 兰溪市| 新巴尔虎右旗| 小金县| 栾川县| 浦江县| 武川县| 临安市| 天等县| 喀喇沁旗| 澎湖县| 兴城市| 柳州市| 子洲县| 古交市| 霍山县| 新野县| 郸城县| 托克托县| 泽州县| 苗栗县| 大渡口区| 壶关县| 南岸区| 满洲里市| 花莲市| 双辽市| 东阳市| 芜湖市| 寿阳县| 抚顺县| 临汾市| 九龙城区|