12

汎用キャッシュマネージャーを実装しようとしていますが、ロックを実行する方法がわかりません。

これまでに次のようなものがありますが、同じリターンタイプのキャッシュエントリが2つある場合は、同じロックオブジェクトが使用されると思います。

public class CacheManager : ICacheManager
{
    static class TypeLock<T>
    {
        public static readonly object SyncLock = new object();
    }
    private readonly ICache _cache;
    public CacheManager(ICache cache)
    {
        if (cache == null)
            throw new ArgumentNullException("cache");

        _cache = cache;
    }

    public TResult AddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        return AddCache(cacheKey, null, acquire, cacheDurationInMinutes);
    }

    public TResult AddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        var entry = acquire.Invoke();
        if (entry != null)
        {
            if (dependency != null)
                _cache.InsertWithDependency(cacheKey, entry, dependency, DateTime.Now.AddMinutes(cacheDurationInMinutes));
            else
                _cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
        }
        return entry;
    }

    public TResult GetOrAddCache<TResult>(string cacheKey, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        return GetOrAddCache(cacheKey, null, acquire, cacheDurationInMinutes);
    }

    public TResult GetOrAddCache<TResult>(string cacheKey, CacheDependency dependency, Func<TResult> acquire, int cacheDurationInMinutes) where TResult : class
    {
        var entry = _cache.GetItem(cacheKey) as TResult;

        if (entry == null)
        {
            lock (TypeLock<TResult>.SyncLock)
            {
                entry = _cache.GetItem(cacheKey) as TResult;
                if (entry == null)
                {
                    entry = acquire.Invoke();
                    if (entry != null)
                    {
                        if (dependency != null)
                            _cache.InsertWithDependency(cacheKey, entry, dependency,
                                                        DateTime.Now.AddMinutes(cacheDurationInMinutes));
                        else
                            _cache.Insert(cacheKey, entry, DateTime.Now.AddMinutes(cacheDurationInMinutes));
                    }
                }
            }
        }

        return entry;
    }
}

どんな助けでも大歓迎です!

4

3 に答える 3

1

その通りです。これは、同じタイプのすべてのキャッシュ エントリに対して同じロックを使用します。実際のキャッシュ方法 (メモリ、ファイル、データベースなど) をこのキャッシュ マネージャーから独立させておくために、キャッシュ エントリごとに追加の同期オブジェクトを保存することをお勧めしますTuple<object, TResult>。for each エントリであり、ロックに使用されます。TResultobjectnew object()

于 2012-11-22T22:01:20.980 に答える
0

ロックを使用する必要があるかどうかわかりませんが、ICache インターフェイスの代わりに MemoryCache を使用しないのはなぜですか? メモリキャッシュは十分に一般的ではありませんか? キャッシュ時間を強制的に分単位にしたのはなぜですか。タイムスパンをキャッシュメソッドに渡す必要があります。私はより一般的です。

数か月前にあるバージョンのキャッシュ マネージャーを実装しましたが、それは Web 指向でした。

于 2014-09-05T19:44:40.857 に答える