我正在将IMemoryCache集成到项目中,并且竭尽全力确保每个存储库或提供程序中的密钥不冲突(即提供密钥空间)。但是后来我想到了,为什么不只为每个存储库/提供者提供他们自己的IMemoryCache单例实例-即一个命名的单例。这将确保密钥永远不会冲突,并且一个存储库永远都无法访问另一个存储库的内部状态。我的原始方面还说,这可能会提高性能,因为现在每个存储库都没有竞争IMemoryCache的内部锁。
但是我不会假装理解IMemoryCache如何管理所有逻辑。也许拥有一个应用程序范围内的单例实例很重要,这样它才能以更高性能的方式管理缓存条目的生存期。
基本上,我从未见过有人使用IMemoryCache的单一存储库模式,因此我正在征求有关此方法的反馈。
谢谢
答案 0 :(得分:2)
我相信原始的.NET完整框架MemoryCache打算通过MemoryCache.Default
属性用作单例实例。这是因为它对称为MemoryPressure
的东西起作用。关于这个神奇的MemoryPressure
实际计算方式的文献几乎为零。毫无疑问,它在多个实例上可能并不太聪明。
现在看来,首选是在缓存上设置大小限制。在dotnet核心版本中,MemoryCache.Default
静态属性不再存在,并且似乎没有警告表明多实例是反模式。此外,似乎MemoryCacheOptions.CompactOnMemoryPressure
现在已过时,首选提供固定的大小。我看不到使用多个实例的任何问题。
答案 1 :(得分:0)
这是我创建的linqpad示例。我认为这就是您要寻找的东西:
void Main()
{
DataTable dt = new DataTable();
DateTime start = DateTime.Now;
Random _rand = new Random();
List<int> result = Enumerable.Range(1, 6000)
.Select(x => x++)
.ToList();
result.AsParallel<int>().ForAll(c =>
{
Util.GetFromCache("datatable", c);
System.Threading.Thread.Sleep(1);
});
DateTime.Now.Subtract(start).Seconds.Dump();
"....DONE.....".Dump();
}
public static class Util
{
private static readonly object _Lock = new object();
public static object GetFromCache(string cachename, int i)
{
object obj = MemoryCacher.GetValue(cachename);
// if (i == 5) //when time is up - reset token, update DB and add to cache es example i set a count=5
// {
// obj = null;
// MemoryCacher.Delete(cachename);
// }
if (obj == null)
{
lock (_Lock)
{
obj = MemoryCacher.GetValue(cachename);
if (obj == null)
{
$"{i} from DATA".Dump();
obj = GetData();
MemoryCacher.Delete(cachename);
MemoryCacher.Add(cachename, obj, DateTimeOffset.Now.AddSeconds(5));
return obj;
}
$"{i} from CACHE with lock".Dump();
}
}
$"{i} from CACHE".Dump();
return obj;
}
public static DataTable GetData()
{
DataTable dt = new DataTable();
FileInfo fi = new FileInfo("c:\\1\\text.txt");
dt = CSVtoDS(fi.FullName, true).AsEnumerable().Take(10).CopyToDataTable();
return dt.Dump("call");
}
public static DataTable CSVtoDS(string filePath, bool isFirstLineHeader)
{
DataTable dt = new DataTable();
using (TextReader tr = File.OpenText(filePath))
{
string strRow = string.Empty;
string[] arrColumns = null;
int indx = 0;
while ((strRow = tr.ReadLine()) != null)
{
//set up columns
if (indx == 0)
{
arrColumns = strRow.Split('\t')[0].Split(',').Select(x => x.Replace(" ", "_")).ToArray();
if (dt.Columns.Count != arrColumns.Length + 1)
for (int i = 0; i <= arrColumns.Length - 1; i++)
{
if (isFirstLineHeader)
dt.Columns.Add(new DataColumn(arrColumns[i]));
else
dt.Columns.Add(new DataColumn());
}
indx = 1;
}
else
{
DataRow dr = dt.NewRow();
dr.ItemArray = strRow.Split(',');
dt.Rows.Add(dr);
}
}
tr.Close();
}
return dt;
}
public static class MemoryCacher
{
public static object GetValue(string key)
{
MemoryCache memoryCache = MemoryCache.Default;
return memoryCache.Get(key);
}
public static void Add(string key, object value, DateTimeOffset absExpiration)
{
MemoryCache memoryCache = MemoryCache.Default;
memoryCache.Set(key, value, absExpiration);
}
public static void Delete(string key)
{
MemoryCache memoryCache = MemoryCache.Default;
if (memoryCache.Contains(key))
{
memoryCache.Remove(key);
}
}
}
}