如果您想了解c#–MemoryCache在第一次到期后总是返回“null”和c#memorypool的知识,那么本篇文章将是您的不二之选。我们将深入剖析c#–MemoryCache在第一次到期后总是返
如果您想了解c# – MemoryCache在第一次到期后总是返回“null”和c# memorypool的知识,那么本篇文章将是您的不二之选。我们将深入剖析c# – MemoryCache在第一次到期后总是返回“null”的各个方面,并为您解答c# memorypool的疑在这篇文章中,我们将为您介绍c# – MemoryCache在第一次到期后总是返回“null”的相关知识,同时也会详细的解释c# memorypool的运用方法,并给出实际的案例分析,希望能帮助到您!
本文目录一览:- c# – MemoryCache在第一次到期后总是返回“null”(c# memorypool)
- .NET Core Cache [MemoryCache]
- .Net Core MemoryCache PostEvictionCallback无法正常工作
- .net core MemoryCache缓存
- .Net Core 中 MemoryCache 使用
c# – MemoryCache在第一次到期后总是返回“null”(c# memorypool)
public class CacheManager : ICacheManager { private readonly ObjectCache cache; public CacheManager() { this.cache = MemoryCache.Default; } public void AddItem(string key,object itemToCache,double duration) { var end = DateTime.Now.AddSeconds(duration); this.cache.Add(key,itemToCache,end); } public T Get<T>(string key) where T : class { try { return (T)this.cache[key]; } catch (Exception ex) { return null; } } public void Remove(string key) { this.cache.Remove(key); } }
很简单
编辑I(问题文本中的错误修复)
问题:当任何密钥的缓存过期时,以下所有调用以获取缓存中的任何对象都将返回“null”.我检查钥匙,总是正确的.
问题仅发生在我的PC中的客户端服务器中,并且我的服务器工作正常.
谢谢.
编辑II(进展)
当我们在客户的服务器中重新启动应用程序池时,您的问题将在几个小时内解决.
我们的网站有一个特定的应用程序池,具有以下设置:
管道管理器模式:集成
框架:v4.0
启用32位应用程序:True.
其他设置,如默认.
在服务器上,我们有2个站点,一个启用了“启用32位应用程序”,如果两个站点都被禁用,则发生错误,但不知道这是否是问题.
编辑III(进展)
由于我们未能解决问题,我们决定切换到Httpcontext.Current.Cache,我们可以解决问题.我们想要另一种解决方案并继续使用MemoryCache,但没有结果.
解决方法
见这个帖子:MemoryCache Empty : Returns null after being set
.NET Core Cache [MemoryCache]
参考资料:long0801的博客、MemoryCache微软官方文档
添加对Microsoft.Extensions.Caching.Memory命名空间的引用,它提供了.NET Core默认实现的MemoryCache类,以及全新的内存缓存API
代码如下:
using System;
using Microsoft.Extensions.Caching.Memory;
namespace FrameWork.Common.DotNetCache
{
public class CacheHelper
{
static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions());
/// <summary>
/// 获取缓存中的值
/// </summary>
/// <param name="key">键</param>
/// <returns>值</returns>
public static object GetCacheValue(string key)
{
if ( !string.IsNullOrEmpty(key) && Cache.TryGetValue(key, out var val))
{
return val;
}
return default(object);
}
/// <summary>
/// 设置缓存
/// </summary>
/// <param name="key">键</param>
/// <param name="value">值</param>
public static void SetCacheValue(string key, object value)
{
if (!string.IsNullOrEmpty(key))
{
Cache.Set(key, value, new MemoryCacheEntryOptions
{
SlidingExpiration = TimeSpan.FromHours(1)
});
}
}
}
}
.Net Core MemoryCache PostEvictionCallback无法正常工作
我想在每次缓存项到期时触发回调,但在我查询缓存中过期的缓存项之前,不会触发回调.
这是代码:
using System; using Microsoft.Extensions.Caching.Memory; namespace Memcache { public class Program { private static MemoryCache _cache; private static int _cacheExpSecs; public static void Main(string[] args) { _cache = new MemoryCache(new MemoryCacheOptions()); _cacheExpSecs = 2; var cacheEntryOptions = new MemoryCacheEntryOptions() .SetSlidingExpiration(TimeSpan.FromSeconds(_cacheExpSecs)) .RegisterPostevictionCallback(callback: evictionCallback); _cache.Set(1,"One",cacheEntryOptions); _cache.Set(2,"Two",cacheEntryOptions); var autoEvent = new System.Threading.AutoResetEvent(false); System.Threading.Timer timer = new System.Threading.Timer(checkCache,autoEvent,1000,6000); Console.Read(); } private static void checkCache(Object o) { if(_cache.Get(1)!=null) { Console.WriteLine(string.Format(@"checkCache: Cache with key {0} will be removed manually and will trigger the callback.",1)); _cache.Remove(1); } else { Console.WriteLine(string.Format("checkCache: Cache with key {0} is expired.",1)); } if(_cache.Get(2) != null) { Console.WriteLine(string.Format("checkCache: Cache with key {0} will expire in {1} seconds,but won't trigger the callback until we check it's value again.",2,_cacheExpSecs)); } else { Console.WriteLine(string.Format("checkCache: Cache with key {0} is expired.",2)); } } private static void evictionCallback(object key,object value,evictionReason reason,object state) { Console.WriteLine(); Console.WriteLine("/*****************************************************/"); Console.WriteLine(string.Format("/* evictionCallback: Cache with key {0} has expired. */",key)); Console.WriteLine("/*****************************************************/"); Console.WriteLine(); } } }
解决方法
(来自MemoryCacheStore.Get(MemoryCacheKey key)
的来源)
internal MemoryCacheEntry Get(MemoryCacheKey key) { MemoryCacheEntry entry = _entries[key] as MemoryCacheEntry; // has it expired? if (entry != null && entry.UtcAbsExp <= DateTime.UtcNow) { Remove(key,entry,CacheEntryRemovedReason.Expired); entry = null; } // update outside of lock UpdateExpAndUsage(entry); return entry; }
或者由于记忆压力而在内部调用Trim()
(来自TrimInternal(int percent)
的来源)
/*SNIP*/ trimmedOrExpired = _expires.FlushExpiredItems(true); if (trimmedOrExpired < toTrim) { trimmed = _usage.FlushUnderUsedItems(toTrim - trimmedOrExpired); trimmedOrExpired += trimmed; } /*SNIP*/
如果您的系统当前内存不足以触发修剪,那么唯一可以驱逐项目的时间是尝试检索它们的时间.
.net core MemoryCache缓存
/// <summary>
/// 缓存帮助类
/// </summary>
public class MemoryCacheHelper
{
private static readonly MemoryCache Cache = new MemoryCache(new MemoryCacheOptions());
/// <summary>
/// 验证缓存项是否存在
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public static bool Exists(string key)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
return Cache.TryGetValue(key, out _);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresSliding">滑动过期时长(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <param name="expiressAbsoulte">绝对过期时长</param>
/// <returns></returns>
public static bool Set(string key, object value, TimeSpan expiresSliding, TimeSpan expiressAbsoulte)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
if (value == null)
throw new ArgumentNullException(nameof(value));
Cache.Set(key, value,
new MemoryCacheEntryOptions().SetSlidingExpiration(expiresSliding)
.SetAbsoluteExpiration(expiressAbsoulte));
return Exists(key);
}
/// <summary>
/// 添加缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <param name="value">缓存Value</param>
/// <param name="expiresIn">缓存时长</param>
/// <param name="isSliding">是否滑动过期(如果在过期时间内有操作,则以当前时间点延长过期时间)</param>
/// <returns></returns>
public static bool Set(string key, object value, TimeSpan expiresIn, bool isSliding = false)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
if (value == null)
throw new ArgumentNullException(nameof(value));
Cache.Set(key, value,
isSliding
? new MemoryCacheEntryOptions().SetSlidingExpiration(expiresIn)
: new MemoryCacheEntryOptions().SetAbsoluteExpiration(expiresIn));
return Exists(key);
}
#region 删除缓存
/// <summary>
/// 删除缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public static void Remove(string key)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
Cache.Remove(key);
}
/// <summary>
/// 批量删除缓存
/// </summary>
/// <returns></returns>
public static void RemoveAll(IEnumerable<string> keys)
{
if (keys == null)
throw new ArgumentNullException(nameof(keys));
keys.ToList().ForEach(item => Cache.Remove(item));
}
#endregion
#region 获取缓存
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public static T Get<T>(string key) where T : class
{
if (key == null)
throw new ArgumentNullException(nameof(key));
return Cache.Get(key) as T;
}
/// <summary>
/// 获取缓存
/// </summary>
/// <param name="key">缓存Key</param>
/// <returns></returns>
public static object Get(string key)
{
if (key == null)
throw new ArgumentNullException(nameof(key));
return Cache.Get(key);
}
/// <summary>
/// 获取缓存集合
/// </summary>
/// <param name="keys">缓存Key集合</param>
/// <returns></returns>
public static IDictionary<string, object> GetAll(IEnumerable<string> keys)
{
if (keys == null)
throw new ArgumentNullException(nameof(keys));
var dict = new Dictionary<string, object>();
keys.ToList().ForEach(item => dict.Add(item, Cache.Get(item)));
return dict;
}
#endregion
/// <summary>
/// 删除所有缓存
/// </summary>
public static void RemoveCacheAll()
{
var l = GetCacheKeys();
foreach (var s in l)
{
Remove(s);
}
}
/// <summary>
/// 删除匹配到的缓存
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public static void RemoveCacheRegex(string pattern)
{
IList<string> l = SearchCacheRegex(pattern);
foreach (var s in l)
{
Remove(s);
}
}
/// <summary>
/// 搜索 匹配到的缓存
/// </summary>
/// <param name="pattern"></param>
/// <returns></returns>
public static IList<string> SearchCacheRegex(string pattern)
{
var cacheKeys = GetCacheKeys();
var l = cacheKeys.Where(k => Regex.IsMatch(k, pattern)).ToList();
return l.AsReadOnly();
}
/// <summary>
/// 获取所有缓存键
/// </summary>
/// <returns></returns>
public static List<string> GetCacheKeys()
{
const BindingFlags flags = BindingFlags.Instance | BindingFlags.NonPublic;
var entries = Cache.GetType().GetField("_entries", flags).GetValue(Cache);
var cacheItems = entries as IDictionary;
var keys = new List<string>();
if (cacheItems == null) return keys;
foreach (DictionaryEntry cacheItem in cacheItems)
{
keys.Add(cacheItem.Key.ToString());
}
return keys;
}
}
.Net Core 中 MemoryCache 使用
1.Demoemo,实际项目中不这么使用
class Program
{
static void Main(string[] args)
{
//缓存的配置
MemoryCacheOptions cacheOps = new MemoryCacheOptions()
{
//缓存最大为100份
//##注意netcore中的缓存是没有单位的,缓存项和缓存的相对关系
SizeLimit = 100,
//缓存满了时,压缩20%(即删除20份优先级低的缓存项)
CompactionPercentage = 0.2,
//两秒钟查找一次过期项
ExpirationScanFrequency = TimeSpan.FromSeconds(3)
};
MemoryCache myCache = new MemoryCache(cacheOps);
//单个缓存项的配置
MemoryCacheEntryOptions cacheEntityOps = new MemoryCacheEntryOptions()
{
//绝对过期时间1
//AbsoluteExpiration = new DateTimeOffset(DateTime.Now.AddSeconds(2)),
//绝对过期时间2
//AbsoluteExpirationRelativeToNow=TimeSpan.FromSeconds(3),
//相对过期时间
SlidingExpiration = TimeSpan.FromSeconds(3),
//优先级,当缓存压缩时会优先清除优先级低的缓存项
Priority = CacheItemPriority.Low,//Low,Normal,High,NeverRemove
//缓存大小占1份
Size = 1
};
//注册缓存项被清除时的回调,可以注册多个回调
cacheEntityOps.RegisterPostEvictionCallback((key, value, reason, state) =>
{
Console.WriteLine($"回调函数输出【键:{key},值:{value},被清除的原因:{reason}】");
});
myCache.Set("mykey", "myvalue", cacheEntityOps);
Console.WriteLine($"mykey的值:{myCache.Get("mykey") ?? "mykey缓存被清除了"}");
Console.WriteLine("------------------暂停3秒");
Thread.Sleep(3000);
Console.WriteLine($"mykey的值:{myCache.Get("mykey") ?? "mykey缓存被清除了"}");
Console.ReadKey();
}
}
}
关于c# – MemoryCache在第一次到期后总是返回“null”和c# memorypool的介绍已经告一段落,感谢您的耐心阅读,如果想了解更多关于.NET Core Cache [MemoryCache]、.Net Core MemoryCache PostEvictionCallback无法正常工作、.net core MemoryCache缓存、.Net Core 中 MemoryCache 使用的相关信息,请在本站寻找。
本文标签: