Вот быстрый, безопасный и поддерживаемый способ сделать это:
static var cacheMap = new ConcurrentDictionary<string, Lazy<byte[]>>();
byte[] RequestSlowOperation(string operationParameter)
{
return cacheMap.GetOrAdd(operationParameter, () => new Lazy<byte[]>(() => RequestSlowOperation2(operationParameter))).Value;
}
byte[] RequestSlowOperation2(string operationParameter)
{
Perform slow task here...
}
Это выполнит RequestSlowOperation2 не более одного раза для каждого ключа.Помните, что память, хранящаяся в словаре, никогда не будет освобождена.
Пользовательский делегат, переданный ConcurrentDictionary, не выполняется под блокировкой, что означает, что он может выполняться несколько раз!Мое решение позволяет создавать несколько лени, но только одна из них будет опубликована и материализована.
Относительно блокировки: это решение будет принимать блокировки, но это не имеет значения, потому что рабочие элементынамного дороже, чем (несколько) операций блокировки.