在第 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”屬性的正確位置適合于數據源控件本身。這還使得數據源控件可以使用一種方法來執行數據訪問,即使多個數據綁定控件被綁定到同一個數據源。至此已多次解釋了該體系結構所蘊涵的這些微妙的概念,但愿能闡明該設計。