1

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

但是,当 Web 池进程优雅地终止时会发生什么?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];
            }
        }
    }
}
4

1 回答 1

1

好的,通过挖掘MemoryCacheMemoryCacheStore源代码,缓存似乎在域卸载时自动处理,此时它处理所有存储,这反过来又删除了缓存项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();
        }
    }
于 2015-02-17T11:00:00.400 回答