本篇將深入探討資料預載入的設計理念與實作細節。這部分內容不涉及 SQL 優化,著重於 GIX4 專案中如何設計符合業務需求的預載入類庫。
預載入的核心概念是在真正需要使用資料之前,利用背景執行緒非同步將資料載入完成。當業務邏輯正式需要資料時,資料已就緒,無需等待漫長的載入過程,從而大幅提升程式回應速度。
適用場景:當我們能預判程式後續步驟極大機率會用到某些資料,且獲取這些資料的操作相當耗時時,即可引入預載入機制,提前備妥資料。
預載入必須採用非同步方式,即使用後台執行緒載入資料,避免阻塞主執行緒(若當前執行緒本身即為非同步載入執行緒,則無需再開新執行緒)。.NET Framework 提供多種非同步實現途徑:APM 模式、ThreadPool.QueueUserWorkItem、.NET 4.0 的 Task 類別等。但專案需求決定了我們需要更高層級的抽象封裝。
系統中預載入的使用場景具體要求如下:
ForeAsyncLoader基於上述需求,設計出的核心類別如下:
namespace OpenExpressApp
{
public enum LoaderStatus
{
NotStarted = 0,
Running = 1,
Completed = 2,
Failed = 3,
}
public class ForeAsyncLoader
{
public ForeAsyncLoader(Action loadAction);
public LoaderStatus Status { get; }
public event EventHandler ActionSucceeded;
///
/// 申請啟動執行緒進行預載入。可重入,多次調用僅執行一次 loadAction。
///
public void BeginLoading();
///
/// 重設載入器。重設後,再次申請預載入將重新執行 loadAction。
///
public void Reset();
///
/// 等待資料載入完成。
///
public void WaitForLoading();
}
}
內部實現基於簡單的執行緒池與同步機制(Monitor/AutoResetEvent),確保執行緒安全與重入特性。
public class DataHolder
{
private object _data;
public object Data { get { return this._data; } }
private object GetDataFromWeb() { /* 耗時的資料獲取邏輯 */ }
private ForeAsyncLoader _dataLoader;
public ForeAsyncLoader DataLoader
{
get
{
if (this._dataLoader == null)
{
this._dataLoader = new ForeAsyncLoader(() =>
{
this._data = this.GetDataFromWeb();
});
}
return this._dataLoader;
}
}
}
public class DataConsumer
{
private void Process(DataHolder holder)
{
holder.DataLoader.WaitForLoading(); // 如已載入完成即時返回,否則等待
var data = holder.Data;
// 使用資料...
}
}
甚至可將 WaitForLoading() 置於 Data 屬性的 get 區塊中,使消費者完全感知不到資料獲取策略的存在。
public class Invoker
{
private DataHolder _holder = new DataHolder();
private void App_Start()
{
this._holder.DataLoader.BeginLoading(); // 立即返回,背景執行緒載入
// 執行其他初始化工作...
}
}

本篇詳細闡述了預載入模式在實際專案中的 API 設計與應用範例。預載入是一個高頻使用的效能優化模式,透過合理的抽象封裝,能讓業務邏輯與資料載入策略解耦,顯著改善使用者體驗。下一篇將結合 GIX4 物件模型,介紹「預載入、延遲載入、聚合 SQL」的組合應用,並補充 CSLA 服務端多線程改造的實戰細節。