2013-05-13 16 views
14

Chcę użyć System.Runtime.Caching.MemoryCache do buforowania niektórych moich obiektów. Chcę mieć pewność, że obiekt jest odświeżany raz dziennie (bezwzględne wygasanie), ale chcę również, aby wygasł, jeśli nie był używany w ciągu ostatniej godziny (wygaśnięcie poślizgu). staram się zrobić:Łączenie przesuwania i bezwzględnego wygasania

object item = "someitem"; 
var cache = MemoryCache.Default; 
var policy = new CacheItemPolicy(); 
policy.AbsoluteExpiration = DateTime.Now.AddDays(1); 
policy.SlidingExpiration = TimeSpan.FromHours(1); 
cache.Add("somekey", item, policy); 

Ale Dostaję „ArgumentException” z „AbsoluteExpiration musi być DateTimeOffset.MaxValue lub SlidingExpiration musi być TimeSpan.Zero”.

Odpowiedz

9

można realizować zarówno upływie systemy pamięci podręcznej za pomocą CacheEntryChangeMonitor. Włóż element pamięci podręcznej bez informacji z bezwzględnym czasem wygaśnięcia, a następnie utwórz pusty monitorZmień ten element i połącz go z drugim elementem pamięci podręcznej, w którym faktycznie zapisujesz informacje slideTimeOut.

 object data = new object(); 
     string key = "UniqueIDOfDataObject"; 
     //Insert empty cache item with absolute timeout 
     string[] absKey = { "Absolute" + key }; 
     MemoryCache.Default.Add("Absolute" + key, new object(), DateTimeOffset.Now.AddMinutes(10)); 

     //Create a CacheEntryChangeMonitor link to absolute timeout cache item 
     CacheEntryChangeMonitor monitor = MemoryCache.Default.CreateCacheEntryChangeMonitor(absKey); 

     //Insert data cache item with sliding timeout using changeMonitors 
     CacheItemPolicy itemPolicy = new CacheItemPolicy(); 
     itemPolicy.ChangeMonitors.Add(monitor); 
     itemPolicy.SlidingExpiration = new TimeSpan(0, 60, 0); 
     MemoryCache.Default.Add(key, data, itemPolicy, null); 
+0

Myślę, że to dobre rozwiązanie, jeśli to działa. Dzięki – Andres

-2

DateTime.Now.AddDays(1) nie zwraca DateTimeOffset, ale DateTime (AddDays()).

Jest to najprawdopodobniej nieważny argument.

Zamiast tego spróbuj DateTimeOffset.Now.AddDays(1) (DateTimeOffset).

+3

-1: Jest [niejawny operator] (http://msdn.microsoft.com/en-us/library /system.datetimeoffset.op_implicit.aspx) z 'DateTime' na' DateTimeOffset'. –

+0

Nie wiedziałem o tym. Dziękuję za aktualizację. – ThaMe90

3

Szybkie odbicie z ILSpy pokazać ten kod podczas wywoływania MemoryCache.Add

if (policy.AbsoluteExpiration != ObjectCache.InfiniteAbsoluteExpiration && policy.SlidingExpiration != ObjectCache.NoSlidingExpiration) 
    { 
     throw new ArgumentException(R.Invalid_expiration_combination, "policy"); 
    } 

Tak, to połączenie z Absolutem i wygasania przesuwne nie są obsługiwane natywnie.

Powinieneś zamienić się w niestandardową implementację.

2

A małe Dodatkowych not dieguitofernandez Odpowiedź (który jest przy okazji, to bardzo dobre rozwiązanie):

ChangeMonitor nie fiering dokładnie w momencie AbsoluteExpiration zostanie osiągnięty, ponieważ nie ma ważności sprawdzane co sekundę. Może upłynąć kilka sekund, zanim powiadomiony zostanie drugi zapisany obiekt. Z 1 dniem jako AbsoluteExpiration nie ma to znaczenia, ale jeśli potrzebujesz dokładnego wygaśnięcia (tak jak ja), musisz najpierw użyć zarówno klawiszy, jak i klawisza absolut.

if (cache.Contains("Absolute" + key) && cache.Contains(key)) 

W ten sposób oba wygaśnięcia są sprawdzane natychmiast i możesz mieć pewność, że element nie wygasł.

(mogę pisać to jako komentarz, bo jestem tu nowy, przepraszam!)