Nie ma potrzeby blokowania całej instancji pamięci podręcznej, wystarczy tylko zablokować określony klucz, dla którego wstawiasz. To znaczy nie ma potrzeby blokowania dostępu do toalety żeńskiej podczas korzystania z toalety męskiej :)
Poniższa implementacja umożliwia blokowanie określonych kluczy pamięci podręcznej przy użyciu współbieżnego słownika. W ten sposób możesz uruchomić GetOrAdd () dla dwóch różnych kluczy w tym samym czasie - ale nie dla tego samego klucza w tym samym czasie.
using System;
using System.Collections.Concurrent;
using System.Web.Caching;
public static class CacheExtensions
{
private static ConcurrentDictionary<string, object> keyLocks = new ConcurrentDictionary<string, object>();
public static T GetOrAdd<T>(this Cache cache, string key, int durationInSeconds, Func<T> factory)
where T : class
{
var value = cache.Get(key);
if (value == null)
{
lock (keyLocks.GetOrAdd(key, new object()))
{
value = cache.Get(key);
if (value == null && (value = factory()) != null)
{
cache.Insert(
key: key,
value: value,
dependencies: null,
absoluteExpiration: DateTime.Now.AddSeconds(durationInSeconds),
slidingExpiration: Cache.NoSlidingExpiration,
priority: CacheItemPriority.Default,
onRemoveCallback: null);
}
keyLocks.TryRemove(key, out object locker);
}
}
return value as T;
}
}