0

我目前正在做的是将一个项目添加到缓存中,并在从缓存中删除该对象时处理我的对象。逻辑是当内存消耗太高时它会被删除。我愿意接受其他建议,但如果可能的话,我想避免创建线程而不是持续测量内存统计信息。这是我的代码:

public class WebServiceCache : ConcurrentDictionary<string, WebServiceCacheObject>, IDisposable
{
    private WebServiceCache()
    {
        if (HttpContext.Current != null && HttpContext.Current.Cache != null)
        {
            HttpContext.Current.Cache.Add("CacheTest", true, null, DateTime.Now.AddYears(1), System.Web.Caching.Cache.NoSlidingExpiration, 
                System.Web.Caching.CacheItemPriority.Low, 
                (key, obj, reason) => {
                    if (reason != System.Web.Caching.CacheItemRemovedReason.Removed)
                    {
                        WebServiceCache.Current.ClearCache(50);
                    }
                });
        }
    }

    private static WebServiceCache _current;
    public static WebServiceCache Current
    {
        get
        {
            if (_current != null && _current.IsDisposed)
            {
                // Might as well clear it fully
                _current = null;
            }
            if (_current == null)
            {
                _current = new WebServiceCache();
            }
            return _current;
        }
    }


    public void ClearCache(short percentage)
    {
        try
        {
            if (percentage == 100)
            {
                this.Dispose();
                return;
            }
            var oldest = _current.Min(c => c.Value.LastAccessed);
            var newest = _current.Max(c => c.Value.LastAccessed);
            var difference = (newest - oldest).TotalSeconds;
            var deleteBefore = oldest.AddSeconds((difference / 100) * percentage);
            // LINQ doesn't seem to work very well on concurrent dictionaries
            //var toDelete = _current.Where(c => DateTime.Compare(c.Value.LastAccessed,deleteBefore) < 0);
            var keys = _current.Keys.ToArray();
            foreach (var key in keys)
            {
                if (DateTime.Compare(_current[key].LastAccessed, deleteBefore) < 0)
                {
                    WebServiceCacheObject tmp;
                    _current.TryRemove(key, out tmp);
                    tmp = null;
                }
            }
            keys = null;
        }
        catch
        {
            // If we throw an exception here then we are probably really low on memory
            _current = null;
            GC.Collect();
        }
    }

    public bool IsDisposed { get; set; }
    public void Dispose()
    {
        this.Clear();
        HttpContext.Current.Cache.Remove("CacheTest");
        this.IsDisposed = true;
    }
}

在 Global.asax

    void context_Error(object sender, EventArgs e)
    {
        Exception ex = _context.Server.GetLastError();
        if (ex.InnerException is OutOfMemoryException)
        {
            if (_NgageWebControls.classes.Caching.WebServiceCache.Current != null)
            {
                _NgageWebControls.classes.Caching.WebServiceCache.Current.ClearCache(100);
            }
        }
    }

谢谢,

4

1 回答 1

2

您可以从应用程序中的任何位置访问 ASP.NET 缓存作为静态属性:

HttpRuntime.Cache

您不需要在 Request 的上下文中(即不需要HttpContext.Current)来执行此操作。

所以你应该使用它而不是滚动你自己的缓存解决方案。

于 2013-07-05T14:31:28.973 回答