2015-02-17 3 views
1

Я использую System.Runtime.MemoryCache в слое интеграции веб-сервисов, чтобы сохранить некоторые списки продуктов, которые являются внешними и медленными для извлечения. Тем не менее, я хочу обновить их, поскольку они истекают, чтобы освободить моих абонентов от ожидания на нем. По этой причине я предварительно использую этот кеш с помощью IIS7.5 и имею RemovedCallback, чтобы перезагрузить данные по истечении срока действия.MemoryCache избегает обновления при выключении

Однако, что происходит, когда процесс веб-пула грациозно умирает? MemoryCache является одноразовым, поэтому он удалит мой объект, и в этот момент я попытаюсь вставить новый экземпляр обратно, оставив весь процесс приостановленным. Есть ли способ для меня безопасно обнаружить, что я не должен перезагружать данные?

internal class ProductCache { 
    private static object _lock = new object(); 
    private static string _cid = Guid.NewGuid().ToString(); 

    public static Product[] data 
    { 
     get 
     { 
      lock (_lock) 
      { 
       if (!MemoryCache.Default.Contains(_cid)) 
       { 
        Product[] p; 
        try 
        { 
         // load data into p 
        } 
        catch (System.Exception e) 
        { 
         Helper.SafeSendExceptionEmail("Integrator.Caching", e); 
         throw e; 
        } 
        MemoryCache.Default.Add(_cid, p, new CacheItemPolicy() 
        { 
         AbsoluteExpiration = DateTimeOffset.Now.AddHours(8), 
         RemovedCallback = arg => 
         { 
          // query again to force reload 
          var d = data; 
         } 
        }); 
       } 
       return (Product[])MemoryCache.Default[_cid]; 
      } 
     } 
    } 
} 
+0

'RemovedCallback' получает' CacheEntryRemovedArguments' экземпляр, который имеет ' RemovedReason'. Я предполагаю (но не проверял), что это только «RemovedReason.Expired», когда запись действительно заканчивается. –

+0

Он также может быть выселен, если память ограничена и т. Д. Я не вижу в списке причины «Я закрываю, поэтому вышвырнул». Существует одна неопределенная причина ('CacheSpecificEviction = 4, // Кэш-запись была выселена по причине, определенной определенным кешем'), но это кажется слишком неоднозначным ... – mmix

+0

Но вас интересует только перезагрузка, если запись * истекает *, правильно? Вам не нужно знать, закрывается ли кеш, только если ваша запись удалена из-за истечения срока действия. Вы не хотите перезагружать его, если его удаляли в любой другой период времени (представьте, какой беспорядок вы получите, если кеш пытается удалить записи из-за давления памяти, и вы забрасываете их обратно!) –

ответ

1

Хорошо, роя через MemoryCache и MemoryCacheStore источника, кажется, что кэш автоматически, расположенный на домене выгрузки в этот момент он располагает всеми магазинами, которые, в свою очередь, удалять элементы кэша с CacheSpecificEviction причине. Эта причина нигде не используется, поэтому он должен представлять «Я умираю» причину (они могли бы быть более ясным в документации, хотя)

public void Dispose() 
    { 
     if (Interlocked.Exchange(ref this._disposed, 1) == 0) 
     { 
      this._expires.EnableExpirationTimer(false); 
      ArrayList list = new ArrayList(this._entries.Count); 
      lock (this._entriesLock) 
      { 
       foreach (DictionaryEntry entry in this._entries) 
       { 
        MemoryCacheEntry entry2 = entry.Value as MemoryCacheEntry; 
        list.Add(entry2); 
       } 
       foreach (MemoryCacheEntry entry3 in list) 
       { 
        MemoryCacheKey key = entry3; 
        entry3.State = EntryState.RemovingFromCache; 
        this._entries.Remove(key); 
       } 
      } 
      foreach (MemoryCacheEntry entry4 in list) 
      { 
       this.RemoveFromCache(entry4, CacheEntryRemovedReason.CacheSpecificEviction, false); 
      } 
      this._insertBlock.Close(); 
     } 
    }