共用方式為


HOW TO:當項目從快取移除時告知應用程式

更新:2007 年 11 月

在大部分的快取案例中,當項目從快取移除時,在下次再用到項目之前您不需要把它放回快取中。一般的開發模式是在使用項目之前永遠先檢查快取。如果項目在快取中就使用它。如果項目不在快取中,就再次擷取該項目並將該項目加回快取中。

然而,在某些情況下當項目從快取移除時,告知應用程式是很有用的。例如,您可能有需要相當長的處理時間才能建立的已快取報表。當從快取移除它時,您想要重新產生報表並且立即放回快取中,讓使用者下一次要求報表時不需要再等候處理。

若要啟用從快取移除項目的告知,ASP.NET 提供 CacheItemRemovedCallback 委派,而這個委派會定義您在撰寫回應從快取移除項目的事件處理常式時所要使用的簽章。ASP.NET 也提供用來指定快取項目移除原因的 CacheItemRemovedReason 列舉型別。

一般來說,您會藉由在管理嘗試擷取之特定快取資料的商務物件中,建立處理常式以實作回呼。例如,ReportManager 物件有 GetReport 和 CacheReport 兩個方法。GetReport 報表方法會檢查快取,查看報表是否已經快取;如果報表沒有快取,方法會重新產生報表然後快取它。CacheReport 方法與 CacheItemRemovedCallback 委派有相同的函式簽章;當此報表自快取中移除時,ASP.NET 會呼叫 CacheReport 方法將報表重新加入快取中。

若要在項目自快取中移除時告知應用程式

  1. 建立負責從快取擷取項目的類別,然後處理回呼方法將項目加回快取中。

  2. 在類別中建立將項目加入快取的方法。

  3. 在類別中建立從快取取得項目的方法。

  4. 建立處理快取項目移除回呼的方法。這個方法必須與 CacheItemRemovedCallback 委派有相同的函式簽章。在方法中,執行當從快取移除項目時想要執行的邏輯,例如重新產生項目然後將其加回快取。

若要測試快取項目回呼

  1. 建立一個 ASP.NET Web 網頁,此網頁會呼叫類別中將項目加入快取的方法。

    下列程式碼範例會示範如何呼叫 ReportManager 類別的 GetReport 方法 (定義在程序後的範例中)。然後會在網頁的 Page_Load 方法期間,在名為 Label1 的 Label 控制項中顯示報表。

    protected void Page_Load(object sender, EventArgs e)
    {
        this.Label1.Text = ReportManager.GetReport();
    }
    
    Protected Sub Page_Load(ByVal sender As Object, _
            ByVal e As System.EventArgs) Handles Me.Load
        Me.Label1.Text = ReportManager.GetReport()
    End Sub
    
  2. 在瀏覽器中要求此 ASP.NET Web 網頁然後檢視報表。

    在第一次要求網頁時會建立報表,並且後續的要求會從快取存取報表直到移除報表為止。

範例

下列程式碼範例會示範名為 ReportManager 的完整類別,當從快取刪除項目時會處理告知。這個類別會管理代表長時間執行處理序,並且格式為字串的報表。

雖然範例會使用宣告為 static (在 Visual Basic 中為 Shared) 的類別,但是並不需要使用靜態類別。然而,當刪除快取項目時必須存在處理回呼的方法。例如,您不應該在 ASP.NET Web 網頁中實作回呼處理常式,因為當從快取刪除項目時可能已經處置過網頁,所以無法使用處理回呼的方法。讓處理回呼的方法使用靜態類別,可以確保當從快取移除項目時,方法仍然存在。然而,靜態類別的缺點是所有靜態方法都需要具備執行緒安全。

警告:

請勿將 CacheItemRemovedCallback 設定為網頁中的方法。除了在處置網頁後無法使用的回呼網頁方法以外,將回呼指向網頁方法可以避免網頁使用的記憶體被記憶體回收重新回收。因為回呼包含網頁參考,並且如果項目中有任何參考,記憶體回收行程不會從記憶體移除項目,所以就會發生這種情況。在應用程式載入期間,這可能會導致快速耗盡記憶體。

範例類別包含下列功能:

  • 追蹤報表是否已經自快取中移除的 Private 成員。

  • 名為 CacheReport 的方法會將項目以 MyReport 為名稱加入快取,然後將項目設定為加入快取一分鐘後過期。這個方法也會將 ReportRemovedCallback 方法傳遞至 onRemoveCallback 參數以註冊 ReportRemoveCallback 方法,當從快取刪除項目時就會呼叫這個方法。

  • 名為 GetReport 的方法,可以從快取取得項目。這個方法會判斷快取中是否存在名為 MyReport 的項目。如果項目不存在,方法會呼叫將項目加入快取的 CacheReport,。

  • 名為 ReportRemovedCallback 的方法會處理快取項目移除回呼。ReportRemovedCallback 與 CacheItemRemovedCallback 委派有相同的函式簽章。這個方法會將變數 _reportRemovedFromCache 設定為 true,然後經由 CacheReport 方法將項目加回快取。

using System;
using System.Web;
using System.Web.Caching;
public static class ReportManager
{
    private static bool _reportRemovedFromCache = false;
    static ReportManager()
    { }

    public static String GetReport()
    {
        lock (typeof(ReportManager))
        {
            if (HttpContext.Current.Cache["MyReport"] != null)
                return (string)HttpRuntime.Cache["MyReport"];
            else
            {
                CacheReport();
                return (string)HttpRuntime.Cache["MyReport"];
            }
        }
    }

    public static void CacheReport()
    {
        lock (typeof(ReportManager))
        {
            HttpRuntime.Cache.Add("MyReport",
                CreateReport(), null, Cache.NoAbsoluteExpiration,
                new TimeSpan(0, 1, 0),
                System.Web.Caching.CacheItemPriority.Default,
                new CacheItemRemovedCallback(ReportRemovedCallback));
        }
    }

    private static string CreateReport()
    {
        System.Text.StringBuilder myReport = 
            new System.Text.StringBuilder();
        myReport.Append("Sales Report<br />");
        myReport.Append("2005 Q2 Figures<br />");
        myReport.Append("Sales NE Region - $2 million<br />");
        myReport.Append("Sales NW Region - $4.5 million<br />");
        myReport.Append("Report Generated: " + DateTime.Now.ToString() 
            + "<br />");
        myReport.Append("Report Removed From Cache: " + 
            _reportRemovedFromCache.ToString());
        return myReport.ToString();
    }

    public static void ReportRemovedCallback(String key, object value, 
        CacheItemRemovedReason removedReason)
    {
        _reportRemovedFromCache = true;
        CacheReport();
    }
}
Imports System
Imports System.Web
Imports System.Web.Caching
Public Class ReportManager
    Private Shared _reportRemovedFromCache As Boolean = False
    Shared Sub New()
    End Sub

    Private Sub New()
    End Sub

    Public Shared Function GetReport() As String
        SyncLock (GetType(ReportManager))
            If HttpContext.Current.Cache("MyReport") IsNot Nothing Then
                Return CStr(HttpRuntime.Cache("MyReport"))
            Else
                CacheReport()
                Return CStr(HttpRuntime.Cache("MyReport"))
            End If
        End SyncLock
    End Function

    Public Shared Sub CacheReport()
        SyncLock (GetType(ReportManager))
            HttpRuntime.Cache.Add("MyReport", CreateReport(), _
            Nothing, Cache.NoAbsoluteExpiration, New TimeSpan(0, 1, 0), _
            System.Web.Caching.CacheItemPriority.Default, _
            New CacheItemRemovedCallback(AddressOf ReportRemovedCallback))
        End SyncLock
    End Sub

    Private Shared Function CreateReport() As String
        Dim myReport As New System.Text.StringBuilder()
        myReport.Append("Sales Report<br />")
        myReport.Append("2005 Q2 Figures<br />")
        myReport.Append("Sales NE Region - $2 million<br />")
        myReport.Append("Sales NW Region - $4.5 million<br />")
        myReport.Append("Report Generated: " & _
            DateTime.Now.ToString() & "<br />")
        myReport.Append("Report Removed From Cache: " _
            & _reportRemovedFromCache.ToString())
        Return myReport.ToString()
    End Function

    Public Shared Sub ReportRemovedCallback(ByVal key As String, _
            ByVal value As Object, ByVal removedReason _
            As CacheItemRemovedReason)
        _reportRemovedFromCache = True
        CacheReport()
    End Sub
End Class

請參閱

工作

HOW TO:將項目加入至快取

HOW TO:擷取快取項目的值

HOW TO:從 ASP.NET 中的快取刪除項目

概念

ASP.NET 快取概觀

ASP.NET 的快取組態

快取應用程式資料