MemoryCache–buforowanie w .NET 4.0

W .NET 4.0 dodano (mało chyba popularną) klasę MemoryCache służącą do buforowania danych. Wcześniej programiści znali podobną klasę w ASP.NET. Od wersji 4.0 została ona wydzielona i można z niej teraz korzystać we wszystkich typach aplikacji – także WPF i WinForms.  Za pomocą MemoryCache można ustawić czas  ważności danych w buforze za pomocą czasu absolutnego,  priorytetu, monitorów, które unieważniają dane np. na podstawie zmiany pliku na dysku lub tzw. SlidingExpiration – czasu który upłynął od ostatniego odpytania bufora.

Same API jest bardzo proste. Na przykład aby dodać element do bufora wystarczy:

CacheItemPolicy cachePolicy = new CacheItemPolicy();
cachePolicy.AbsoluteExpiration = new DateTimeOffset(new DateTime(2012, 11, 1));
MemoryCache.Default.Add("klucz", "dowolna wartosc", cachePolicy);

Z kolei aby odczytać z bufora wartość:

string value = MemoryCache.Default.Get("klucz").ToString();

Kilka wyjaśnień:

  1. AbsoluteExpiration – oznacza kiedy dana wartość zostanie skasowana z bufora (absolutny czas ważności).
  2. MemoryCache.Default zwraca domyślny bufor – zwykłe aplikacja potrzebuje tylko jednego MemoeryCache i nie ma potrzeby tworzenia własnych obiektów MemoeryCache.
  3. Gdy bufor straci ważność metoda Get zwraca NULL – stąd powyższy kod jest niebezpieczny ponieważ może wywołać wyjątek null reference  przez ToString().

Oprócz absolutnego czasu ważności możemy zdefiniować wspomniany SlidingException:

CacheItemPolicy cachePolicy = new CacheItemPolicy();
cachePolicy.SlidingExpiration = new TimeSpan(0, 1, 0);

Powyższy kod oznacza, że jeśli wpis w buforze nie będzie wykorzystany (poprzez metodę Get) ani razu w ciągu minuty to zostanie unieważniony.

Do dyspozycji mamy również kilka różnych monitorów:

List<string> paths=new List<string>();
paths.Add("c:\\1.txt");
HostFileChangeMonitor fileChangeMonitor=new HostFileChangeMonitor(paths);
cachePolicy.ChangeMonitors.Add(fileChangeMonitor);

HostFileChangeMonitor sprawdza  czy przekazane przez parametr paths, pliki lub foldery nie zostały zmienione. Monitorowane są m.in. nazwy plików (lub katalogów), rozmiar, ACL czy pliki w danym katalogu. Ponadto do despocji mamy jeszcze następujący monitory:

  1. CacheEntryChangeMonitor – unieważnia wpis w przypadku gdy jakiś inny wpis zostały zmieniony.
  2. SqlChangeMonitor – monitorowanie bazy SQL Server.

Do dyspozycji jest również priorytet, który aktualnie przyjmuje dwie wartości (wydaje mi się, że nazwy mówią same za siebie):

cachePolicy.Priority = CacheItemPriority.Default;
cachePolicy.Priority = CacheItemPriority.NotRemovable;

Oprócz poszczególnych elementów w buforze, można również konfigurować bufor jako całość. Domyślny bufor (zwrócony poprzez właściwość Default) można wyłącznie skonfigurować za pomocą XML (np. w App.config dla aplikacji desktop):

<configuration>
  <system.runtime.caching>
    <memoryCache>
      <namedCaches>
          <add name="default" 
               cacheMemoryLimitMegabytes="0" 
               physicalMemoryPercentage="0"
               pollingInterval="00:02:00" />
      </namedCaches>
    </memoryCache>
  </system.runtime.caching>
</configuration>

Własne bufory można konfigurować zarówno z poziomu pliku XML jak i konstruktora.

4 thoughts on “MemoryCache–buforowanie w .NET 4.0”

  1. Jak nigdy, tym razem napiszę komentarz gloryfikujący idee powstania wpisu. Sam z MemoryCache nie korzystałem, słyszałem że jest ale nie miałem motywacji by się z nim zapoznać. Po przeczytaniu Twojego wpisu rozwiązaniem jest zafascynowany i z pewnością do niego wrócę.

    Świetny wpis. Rzeczowo i bez “polityki” 🙂

  2. Hej,
    Czy próbowałeś uzywać MemoryCache.UpdateCallback ?
    Dostaję dziwny błąd i nie mogę znaleźć nic w dokumentacji:

    “CacheItemUpdateCallback must be null”

  3. Czy da się stosować cache w ramach konkretnego użytkownika czy to działa globalnie na całą aplikację? Powiedzmy dla danego użytkownika tworzona jest specyficzna strona wzorcowa i chciałabym ją buforować. A jeżeli się da to czy to nie wykończy serwera, jeżeli jest dużo użytkowników? Gdzieś wyczytałam że to jest zapisane na serwerze.

Leave a Reply

Your email address will not be published.