程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> ASP.NET >> 關於ASP.NET >> ASP.NET 2.0數據源控件的異步數據訪問

ASP.NET 2.0數據源控件的異步數據訪問

編輯:關於ASP.NET

在第 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);
      }
     }
    ...
}

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved