Condividi tramite


Procedura: notificare all'applicazione la rimozione di un elemento dalla cache

Aggiornamento: novembre 2007

Nella maggior parte degli scenari relativi alla cache, quando un elemento viene rimosso dalla cache non è necessario reinserirlo fino a quando non viene nuovamente richiesto. Di norma, lo sviluppatore tende sempre a controllare la presenza dell'elemento nella cache prima di utilizzarlo. Se l'elemento è presente, è possibile utilizzarlo. In caso contrario, l'elemento viene recuperato e aggiunto nuovamente alla cache.

Tuttavia, in alcuni casi risulta utile informare l'applicazione in merito alla rimozione di un elemento dalla cache. Si supponga, ad esempio, di avere un report memorizzato nella cache la cui elaborazione è particolarmente lunga. Quando viene rimosso dalla cache, è normale che si desideri essere in grado di rigenerarlo e reinserilo immediatamente nella cache, in modo che alla successiva richiesta l'utente non debba attendere che sia elaborato.

Per abilitare la notifica della rimozione degli elementi dalla cache, ASP.NET fornisce il delegato CacheItemRemovedCallback. Il delegato definisce la firma da utilizzare quando si scrive un gestore eventi chiamato in risposta alla rimozione di un elemento dalla cache. ASP.NET fornisce inoltre l'enumerazione CacheItemRemovedReason, utilizzata per specificare i motivi alla base della rimozione dell'elemento dalla cache.

Di norma, viene implementato il callback tramite la creazione di un gestore in un oggetto business che gestisca i dati specifici della cache che si stanno cercando di recuperare. Si supponga, ad esempio, di avere un oggetto ReportManager che ha due metodi: GetReport e CacheReport. Il metodo del report GetReport controlla se nella cache è già memorizzato il report e, in caso contrario, lo rigenera e lo memorizza nella cache. Il metodo CacheReport ha la stessa firma funzione del delegato CacheItemRemovedCallback; quando il report viene rimosso dalla cache, ASP.NET effettua la chiamata al metodo CacheReport, il quale lo inserisce nuovamente nella cache.

Per inviare una notifica all'applicazione quando un elemento viene rimosso dalla cache

  1. Creare una classe responsabile del recupero dell'elemento dalla cache e della gestione del metodo di callback per inserire nuovamente l'elemento nella cache.

  2. Nella classe, creare un metodo in grado di aggiungere un elemento nella cache.

  3. Nella classe, creare un metodo in grado di ottenere un elemento dalla cache.

  4. Creare un metodo in grado di gestire il callback della rimozione dell'elemento dalla cache. Il metodo deve avere la stessa firma funzione del delegato CacheItemRemovedCallback. Nel metodo, applicare la logica che si desidera eseguire quando un elemento viene rimosso dalla cache, come la rigenerazione dell'elemento e il successivo inserimento nella cache.

Per eseguire il test del callback dell'elemento nella cache

  1. Creare una pagina Web ASP.NET che effettua la chiamata del metodo nella classe che aggiunge l'elemento nella cache.

    Nel seguente esempio di codice viene illustrato come effettuare la chiamata del metodo GetReport della classe ReportManager, definita nell'esempio che segue la procedura. Quindi, viene visualizzato il report in un controllo Label denominato Label1 nel corso del metodo Page_Load della pagina.

    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. Richiedere la pagina ASP.NET in un browser e visualizzare il report.

    Il report viene creato nel corso della prima richiesta della pagina. Le successive richieste accedono al report dalla cache fino a quando questo viene rimosso.

Esempio

Nel seguente esempio di codice viene illustrata una classe completa denominata ReportManager che gestisce la notifica relativa alla rimozione di un elemento dalla cache. La classe gestisce un report sotto forma di stringa che rappresenta un processo a esecuzione prolungata.

Benché nell'esempio venga utilizzata una classe dichiarata come static (Shared in Visual Basic), non è necessario utilizzare una classe statica. Tuttavia, è necessario che il metodo di gestione del callback sia presente quando l'elemento viene rimosso dalla cache. Ad esempio, non è opportuno implementare il gestore del callback in una pagina ASP.NET, in quanto la pagina potrebbe essere già stata eliminata quando l'elemento viene rimosso dalla cache e, pertanto, il metodo di gestione del callback non sarà disponibile. Se si utilizza una classe statica per il metodo di gestione del callback, si garantisce che tale metodo sia disponibile quando l'elemento viene rimosso dalla cache. Tuttavia, una classe statica comporta che tutti i metodi statici debbano essere thread safe.

Attenzione:

Non impostare il CacheItemRemovedCallback su un metodo in una pagina. Oltre al fatto che un metodo della pagina non è disponibile per un callback successivamente all'eliminazione della pagina, se il callback fa riferimento a un metodo della pagina è possibile impedire il recupero della memoria utilizzata dalla pagina da parte della procedura di Garbage Collection. Ciò accade perché il callback contiene un riferimento alla pagina e il Garbage Collector non rimuove un elemento dalla memoria se lo stesso è associato a un qualsiasi riferimento. Nei periodi di carico dell'applicazione, la memoria potrebbe esaurirsi molto velocemente.

La classe illustrata nell'esempio comprende le seguenti funzionalità:

  • Un membro privato per verificare se il report è stato rimosso dalla cache.

  • Un metodo denominato CacheReport che aggiunge un elemento alla cache con il nome MyReport e ne imposta la scadenza un minuto dopo che è stato aggiunto alla cache. Il metodo passa anche il metodo ReportRemovedCallback al parametro onRemoveCallback, il quale registra il metodo ReportRemoveCallback in modo che venga chiamato quando l'elemento viene eliminato dalla cache.

  • Un metodo denominato GetReport che ottiene un elemento dalla cache. Il metodo determina se l'elemento denominato MyReport è presente nella cache. Se l'elemento non è presente, il metodo effettua la chiamata al CacheReport,, che aggiunge l'elemento alla cache.

  • Un metodo denominato ReportRemovedCallback che gestisce il callback di rimozione dell'elemento dalla cache. Il ReportRemovedCallback ha la stessa firma funzione del delegato CacheItemRemovedCallback, imposta la variabile _reportRemovedFromCache su true, quindi aggiunge nuovamente l'elemento alla cache tramite il metodo 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

Vedere anche

Attività

Procedura: aggiungere elementi alla cache

Procedura: recuperare i valori degli elementi memorizzati nella cache

Procedura: eliminare gli elementi dalla cache in ASP.NET

Concetti

Cenni preliminari sull'inserimento nella cache in ASP.NET

Configurazione della cache in ASP.NET

Memorizzazione nella cache dei dati dell'applicazione