文章目錄
應用程式狀態允許儲存被所有客戶訪問的全域對象。應用程式狀態基於 System.Web.HttpApplicationState 類,該類在 Web 頁面中通過內建的 Application 對象提供。
例如,可以建立一個 global.asax 事件處理常式來跟蹤有多少會話被建立了,也可以使用相同的邏輯追蹤某一頁面的訪問次數:
protected void Page_Load(object sender, EventArgs e)
{
int count = 0;
if (Application["HitCounterForOrderPage"] != null)
{
count = (int)Application["HitCounterForOrderPage"];
count++;
Application["HitCounterForOrderPage"] = count;
}
}
應用程式狀態用物件類型儲存狀態項,所有集合中取值需要轉換類型。應用程式狀態中項目從不到期,一直被儲存到應用程式或伺服器重啟。
應用程式狀態不太經常使用,因為效率不高。在上一個例子中,計數器的數字不精確,大量使用者同時訪問時,會丟失計數。為了避免這個情況的出現,可以使用 Lock()和 UnLock()方法,它們禁止使用者同時訪問 Application 集合:
protected void Page_Load(object sender, EventArgs e)
{
Application.Lock();
int count = 0;
if (Application["HitCounterForOrderPage"] != null)
{
count = (int)Application["HitCounterForOrderPage"];
count++;
Application["HitCounterForOrderPage"] = count;
}
Application.UnLock();
}
遺憾的是,所有請求該頁面的使用者都將被暫停直到 Application 集合被釋放。這會大大的降低效能。一般而言,經常改變的值不適合放到應用程式狀態中。
事實上,ASP.NET 中極少使用應用程式狀態,因為它的兩個最常用的功能已經被更簡單,更有效方法替代了:
- 以前,人們使用應用程式狀態來儲存應用程式層級的常量,如資料庫連接字串。現在這類常量可以儲存在web.config中,它通常更為靈活,因為它易於修改而不需要更改代碼或重新編譯應用程式。
- 應用程式狀態還可以用來儲存常用但建立較費時的資訊,比如進行資料庫查詢全部產品目錄。但現在更相似,明智的做法是在 ASP.NET 的緩衝中儲存常用的資訊。應用程式狀態的很多應用可以使用緩衝有效替換。
靜態應用程式變數
還可以在 global.asax 檔案中添加靜態成員變數:
public static string[] FileList;
這能夠起作用的關鍵在於變數時靜態。因為 ASP.NET 建立 HttpApplication 類的串連池來服務多個請求。這樣,每次請求都可能由不同的 HttpApplication 對象來服務,每個 HttpApplication 對象都有自己的執行個體資料,然而,待用資料的副本只有一份。
仍然存在多個頁面會調用這個靜態變數的可能性,但是由於不是 Application 對象因此沒有了自動鎖,所以應該使用 C# 的鎖語句來臨時將變數限定於某個單獨的線程裡。
private static Dictionary<string, string> metadata = new Dictionary<string, string>();
public void AddMetadata(string key, string value)
{
lock (metadata)
{
metadata[key] = value;
}
}
public string GetMetadata(string key)
{
lock (metadata)
{
return metadata[key];
}
}
使用靜態成員變數而不使用 Application 集合有兩大優勢。
- 首先,在值被訪問或修改時(通過在屬性過程或者方法中綁定資料),它允許你編寫可自動啟動並執行編碼。可以使用這段代碼記錄某個值被訪問了多少次,可以檢查資料是否依然有效,或者是否需要重新建立。這個樣本使用延遲初始化模式,且僅在第一次請求時建立全域對象:
private static string[] fileList;
public static string[] FileList
{
get
{
if (fileList == null)
{
fileList = Directory.GetFiles(HttpContext.Current.Request.PhysicalApplicationPath);
}
return fileList;
}
}
// 這個樣本使用檔案訪問類來讀取 Web 應用程式的檔案清單
// 這個功能不可能通過 Application 集合實現
- 使用靜態成員變數的另一個好處是型別安全,從 Global 類中取得的變數類型不需要轉換。