我有一些依赖于HttpContext.Cache的代码,如果满足某个条件,我希望它重新缓存一些东西。然而,这引入了潜在的堆栈溢出,我不确定这里适当的方法是什么。
请看这段代码:
void OnCacheItemRemoved( string key, object value, CacheItemRemovedReason reason )
{
var c = value as RequestCounter;
if ( c == null )
return;
if ( .. Some logic that might be true .. )
{
Cache.Insert( key, c, null, DateTime.UtcNow.AddSeconds( timeWindow ),
Cache.NoSlidingExpiration, CacheItemPriority.Low, OnCacheItemRemoved );
}
}
调试时,堆栈跟踪似乎没有建立起来,但在现实生活中,确实如此。这可能取决于如何调用回调(例如,如果由于某种原因立即释放缓存)?
此外,围绕此问题的最佳解决方案是什么?传入一个带有重复代码的委托(可能将除Cache.Insert之外的逻辑移到一个常用方法)?我仍然担心它会建立一个堆栈,我不知道我有什么选择。
有什么建议吗?
答案 0 :(得分:0)
根据我的观察结果添加答案:
在这种情况下防止StackOverflowException的一种解决方案
void OnCacheItemRemoved( string key, object value, CacheItemRemovedReason reason )
{
if ( reason != CacheItemRemovedReason.Expired )
{
return;
}
至少,这可以防止堆栈溢出。 stackoverflow异常原因背后的理论似乎是在替换缓存项(或由插入重新缓存)时调用回调。尝试缓存同一项的两个并行请求将创建一个竞争条件,其中第一个缓存项将被第二个请求过期,从而调用回调,而回调又会再次插入,调用第二个回调并生成在理性的无限失效"删除"。似乎该种族会构建调用堆栈,而过期线程则不会。