MemoryCache 避免在关机时刷新

MemoryCache avoid refreshing on shutdown

我在 Web 服务集成层中使用 System.Runtime.MemoryCache 来保留一些外部的且检索速度较慢的产品列表。但是,我想在它们过期时刷新它们,以使我的呼叫者免于等待。出于这个原因,我正在使用 IIS7.5 预热此缓存,并有一个 RemovedCallback 在过期时重新加载数据。

但是,当网络池进程正常结束时会发生什么? 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];
            }
        }
    }
}

好的,通过挖掘 MemoryCacheMemoryCacheStore 来源,似乎缓存是在域卸载时自动处理的,此时它会处理所有存储,进而删除缓存项有 CacheSpecificEviction 个原因。此原因未在其他任何地方使用,因此它必须代表 "I'm dying" 原因(尽管它们在文档中可能更清楚)

    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();
        }
    }