У меня есть метод расширения для объекта Microsoft.ApplicationServer.Caching.DataCache, найденный в Windows Server AppFabric SDK, который выглядит следующим образом:
using System;
using System.Collections.Generic;
using Microsoft.ApplicationServer.Caching;
namespace Caching
{
public static class CacheExtensions
{
private static Dictionary<string, object> locks = new Dictionary<string, object>();
public static T Fetch<T>(this DataCache @this, string key, Func<T> func)
{
return @this.Fetch(key, func, TimeSpan.FromSeconds(30));
}
public static T Fetch<T>(this DataCache @this, string key, Func<T> func, TimeSpan timeout)
{
var result = @this.Get(key);
if (result == null)
{
lock (GetLock(key))
{
result = @this.Get(key);
if (result == null)
{
result = func();
if (result != null)
{
@this.Put(key, result, timeout);
}
}
}
}
return (T)result;
}
private static object GetLock(string key)
{
object @lock = null;
if (!locks.TryGetValue(key, out @lock))
{
lock (locks)
{
if (!locks.TryGetValue(key, out @lock))
{
@lock = new object();
locks.Add(key, @lock);
}
}
}
return @lock;
}
}
}
Цель состоит в том, чтобы позволить разработчику написать код, который говорит: "выборка мне некоторые данные, сначала попробовав кеш. если он недоступен в кеше, выполните указанную функцию, поместите результаты в кеш для следующего вызывающего абонента, а затем верните результаты ". Примерно так:
var data = dataCache.Fetch("key", () => SomeLongRunningOperation());
Блокировка ограничивает выполнение потенциально длительного вызова функции одним потоком, но только в рамках одного процесса на той же машине. Как бы вы расширили этот шаблон, чтобы сделать блокировку распределенной, чтобы предотвратить одновременное выполнение функции несколькими процессами / машинами?