【问题标题】:How is this cache manager storing the cached data?这个缓存管理器如何存储缓存的数据?
【发布时间】:2016-03-07 19:19:18
【问题描述】:

我正在使用this cache manager, taken from bbarry on github

我不明白缓存数据的实际存储位置或方式。我见过的大多数缓存都使用MemoryCache,但我在任何地方都没有提到这一点。

我只能认为ConcurrentDictionary是存储缓存的数据,但如果是这样,我不明白为什么这是一个设置为readonly

public static class Cache<T> {
    static readonly ConcurrentDictionary<string, T> Dictionary = new ConcurrentDictionary<string, T>();

    //by making this a tuple with the generic constraint, there will be one per cache type; the first parameter will always be the default value
    static readonly ConcurrentDictionary<string, Tuple<T, DateTime, TimeSpan>> Removals = new ConcurrentDictionary<string, Tuple<T, DateTime, TimeSpan>>();


    public static T GetOrAdd(string key, Func<string, T> creator) { return GetOrAdd(key, creator, null, null); }


    public static T GetOrAdd(string key, Func<string, T> creator, DateTime absoluteExpiration) { return GetOrAdd(key, creator, absoluteExpiration, null); }


    public static T GetOrAdd(string key, Func<string, T> creator, TimeSpan slidingExpiration) { return GetOrAdd(key, creator, null, slidingExpiration); }


    public static bool TryGetValue(string key, out T value) {
        Tuple<T, DateTime, TimeSpan> when;
        if (Removals.TryGetValue(key, out when) && when.Item3 != TimeSpan.Zero) {
            Remove(key, Tuple.Create(default(T), DateTime.Now.Add(when.Item3), when.Item3));
        }
        return Dictionary.TryGetValue(key, out value); 
    }


    public static bool Expire(string key, out T value) { return Dictionary.TryRemove(key, out value); }


    public static void Expire(string key) {
        T value;
        Dictionary.TryRemove(key, out value);
    }

    static T GetOrAdd(string key, Func<string, T> creator, DateTime? absoluteExpiration, TimeSpan? slidingExpiration) {
        if (key == null) {
            throw new ArgumentNullException("key");
        }
        Tuple<T, DateTime, TimeSpan> when;
        var updateRemoval = Removals.TryGetValue(key, out when) && when.Item3 != TimeSpan.Zero;
        var v = Dictionary.GetOrAdd(key, creator);
        if (absoluteExpiration == null && slidingExpiration == null && !updateRemoval) {
            return v;
        }
        if (absoluteExpiration != null || slidingExpiration != null) {
            var expiration = (TimeSpan)(slidingExpiration ?? (absoluteExpiration - DateTime.Now));
            when = Tuple.Create(default(T), DateTime.Now.Add(expiration), expiration);
        } else {
            when = Tuple.Create(default(T), DateTime.Now.Add(when.Item3), when.Item3);
        }
        if (absoluteExpiration != null) {
            Removals.TryAdd(key, Tuple.Create(default(T), (DateTime)absoluteExpiration, TimeSpan.Zero));
        } else {
            Removals.AddOrUpdate(key, when, (a, b) => when);
        }

        Remove(key, when);
        return v;
    }

    static void Remove(string key, Tuple<T, DateTime, TimeSpan> then) {
        System.Threading.Tasks.Task.Delay(then.Item3).ContinueWith(task => {
            Tuple<T, DateTime, TimeSpan> when;
            if (!Removals.TryGetValue(key, out when) || when.Item2 >= DateTime.Now)
                return;
            T v;
            Dictionary.TryRemove(key, out v);
            Removals.TryRemove(key, out when);
        });
    }
}

【问题讨论】:

    标签: c# caching concurrentdictionary


    【解决方案1】:

    readonly 修饰符并不意味着您不能修改标有它的集合(在本例中为ConcurrentDictionary&lt;string, T&gt; Dictionary)。

    这只意味着你不能重新分配它的价值。所以在这个例子中你不能这样做

    Dictionary = new ConcurrentDictionary<string, T>();
    

    再次。 readonly 的文档(上面链接)列出了可以分配标记为readonly 的字段的可能位置。在构造函数或静态构造函数或字段声明中。

    您的问题的答案是肯定的,在这种情况下,是 ConcurrentDictionary 存储数据。 (GetOrAdd 方法)。

    【讨论】:

    • 不错的 Szabolcs,感谢您的解释和澄清 :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-09-26
    • 1970-01-01
    • 2018-02-10
    • 2016-01-15
    • 2017-10-06
    • 1970-01-01
    • 2020-06-13
    相关资源
    最近更新 更多