我遇到MemoryCache(System.Runtime.Caching)的问题。关于此对象的其他问题,我发现在域未处理的异常之后没有缓存任何值。
例外是:
Exception: System.TypeInitializationException
Message: The type initializer for 'System.Web.Util.ExecutionContextUtil' threw an exception.
Trace:
at System.Web.Util.ExecutionContextUtil.RunInNullExecutionContext(Action callback)
at System.Web.Hosting.ObjectCacheHost.System.Runtime.Caching.Hosting.IMemoryCacheManager.UpdateCacheSize(Int64 size, MemoryCache memoryCache)
at System.Runtime.Caching.CacheMemoryMonitor.GetCurrentPressure()
at System.Runtime.Caching.MemoryMonitor.Update()
at System.Runtime.Caching.MemoryCacheStatistics.CacheManagerThread(Int32 minPercent)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading._TimerCallback.PerformTimerCallback(Object state)
Caused by Exception: System.Exception Message: Type 'System.Threading.ExecutionContext' does not have a public property named 'PreAllocatedDefault'.
Trace: at System.Web.Util.ExecutionContextUtil.GetDummyDefaultEC()
at System.Web.Util.ExecutionContextUtil..cctor()
异常似乎是在2到5分钟后抛出。我认为解决这个异常应该解决我的问题,因为缓存不会被处理掉。
问题始于昨天19h,即使我使用它3个月...... 自12天以来,生产没有任何变化。服务器托管在Azure上(os是Windows Server 2008 R2)
修改 异常处理程序
public class Global : System.Web.HttpApplication
{
void Application_Start(object sender, EventArgs e) {
System.Threading.Thread.GetDomain().UnhandledException += new UnhandledExceptionEventHandler(Global_UnhandledException);
System.Threading.Thread.GetDomain().DomainUnload += new EventHandler(Global_DomainUnload);
}
}
MemoryCache Wrapper
public abstract class MemoryCacheManager : ICacheManager
{
private MemoryCache MemoryCache;
protected MemoryCacheManager()
{
MemoryCache = new MemoryCache("Common.Utils.MemoryCacheManager");
}
private void ItemRemoved(CacheEntryRemovedArguments arguments)
{
switch (arguments.RemovedReason)
{
case CacheEntryRemovedReason.CacheSpecificEviction:
LogManager.Instance.Log(arguments.CacheItem.Key + " : CacheSpecificEviction");
break;
case CacheEntryRemovedReason.ChangeMonitorChanged:
LogManager.Instance.Log(arguments.CacheItem.Key + " : ChangeMonitorChanged");
break;
case CacheEntryRemovedReason.Evicted:
LogManager.Instance.Log(arguments.CacheItem.Key + " : Evicted");
break;
case CacheEntryRemovedReason.Expired:
LogManager.Instance.Log(arguments.CacheItem.Key + " : Expired");
break;
case CacheEntryRemovedReason.Removed:
LogManager.Instance.Log(arguments.CacheItem.Key + " : Removed");
break;
}
}
#region ICacheManager
public void Add(string key, object value, DateTimeOffset absoluteExpiration)
{
var policy = new CacheItemPolicy { AbsoluteExpiration = absoluteExpiration, RemovedCallback = ItemRemoved };
Add(key, value, policy);
}
public void Add(string key, object value, TimeSpan slidingExpiration)
{
var policy = new CacheItemPolicy { SlidingExpiration = slidingExpiration, RemovedCallback = ItemRemoved };
Add(key, value, policy);
}
private void Add(string key, object value, CacheItemPolicy policy)
{
MemoryCache.Add(key, value, policy);
LogManager.Instance.Info(DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss") + " " + key + " : Added");
}
public object Get(string key)
{
return MemoryCache.Get(key);
}
public bool Exist(string key)
{
return MemoryCache.Contains(key);
}
public bool Remove(string key)
{
return MemoryCache.Remove(key) != null;
}
#endregion
}
缓存管理器
public class CacheManager : MemoryCacheManager
{
#region Singleton
private static readonly CacheManager instance = new CacheManager();
// Explicit static constructor to tell C# compiler ot to mark type as beforefieldinit
static CacheManager() { }
private CacheManager()
: base()
{
}
public static CacheManager Instance
{
get
{
return instance;
}
}
#endregion
}
首次调用Global_UnhandledException后,所有CacheManager.Instance.Get都返回null。
我的问题是:如何避免这种异常?或者如何使memorycache正常工作
答案 0 :(得分:3)
我也遇到了异常,我可以使用HTTP模块输出到文本文件来捕获未处理的异常,这种异常往往发生在页面请求/响应执行之外。
message=The type initializer for 'System.Web.Util.ExecutionContextUtil' threw an exception.
stack= at System.Web.Util.ExecutionContextUtil.RunInNullExecutionContext(Action callback)
at System.Web.Hosting.ObjectCacheHost.System.Runtime.Caching.Hosting.IMemoryCacheManager.UpdateCacheSize(Int64 size, MemoryCache memoryCache)
at System.Runtime.Caching.CacheMemoryMonitor.GetCurrentPressure()
at System.Runtime.Caching.MemoryMonitor.Update()
at System.Runtime.Caching.MemoryCacheStatistics.CacheManagerThread(Int32 minPercent)
at System.Runtime.Caching.MemoryCacheStatistics.CacheManagerTimerCallback(Object state)
at System.Threading._TimerCallback.TimerCallback_Context(Object state)
at System.Threading.ExecutionContext.runTryCode(Object userData)
at System.Runtime.CompilerServices.RuntimeHelpers.ExecuteCodeWithGuaranteedCleanup(TryCode code, CleanupCode backoutCode, Object userData)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean ignoreSyncCtx)
at System.Threading._TimerCallback.PerformTimerCallback(Object state)
type=System.Exception
message=Type 'System.Threading.ExecutionContext' does not have a public property named 'PreAllocatedDefault'.
stack=at System.Web.Util.ExecutionContextUtil.GetDummyDefaultEC()
at System.Web.Util.ExecutionContextUtil..cctor()
编辑:值得注意的是,抛出此异常后,缓存将完全停止工作。
我在研究问题时遇到过这个问题:
在文中他们说:“此OS版本包含标准安全补丁,包括https://support.microsoft.com/kb/2862772(MS13-059)中的修复程序,这是Internet Explorer的累积安全更新。此IE补丁引入了回归在ASP.NET应用程序中使用System.Runtime.Caching.MemoryCache时会导致上述异常。“
后来,他们给出了三个解决方案,第一个是在应用修补程序之前回滚。第二个告诉你简单地避免使用MemoryCache(很好)。唯一的另一个解决方案就是等到修补这个问题并在10月初(2013年)提示。
“下一个Windows Azure客户操作系统版本将包含用于解决此问题的IE修补程序,并应在10月初开始向Azure推出。”
此页面的显示方式听起来好像这个问题只是Windows Azure的一个问题。但我认为它会影响任何具有此修补程序并运行ASP.NET应用程序的平台。虽然Windows 7(这是我的操作系统)的“关键”更新似乎是推出到Windows Server 2008的修补程序被标记为“中等”。这可能会有所帮助,因为虽然它会影响我的开发平台,但它不会影响我的生产服务器。我在下面的安全公告中找到了这些信息:
http://technet.microsoft.com/en-us/security/bulletin/ms13-059
有趣的是,当我不得不在ASP.NET应用程序中添加使用OutputCache进行子操作的解决方案时,我停止了这个问题,尽管我仍然继承MemoryCache。
我会包含我用过的代码,如果它派上用场,我会相信以下博客,为我节省了大量时间:
http://www.haneycodes.net/custom-output-caching-with-mvc3-and-net-4-0-done-right/
以下代码......
public class CustomMemoryCache : MemoryCache
{
public CustomMemoryCache(string name)
: base(name)
{
}
public override bool Add(string key, object value, DateTimeOffset absoluteExpiration, string regionName = null)
{
System.Web.Caching.OutputCache.Providers[System.Web.Caching.OutputCache.DefaultProviderName].Add(key, value, absoluteExpiration.DateTime);
return true;
}
public override object Get(string key, string regionName = null)
{
return System.Web.Caching.OutputCache.Providers[System.Web.Caching.OutputCache.DefaultProviderName].Get(key);
}
}
在我的Global.asax.cs中:
protected void Application_Start()
{
OutputCacheAttribute.ChildActionCache = new CustomMemoryCache("MyCache");
}
提供者:
public class MyCacheItem
{
public Object ItemData { get; set; }
public DateTime UtcExpiry { get; set; }
public DateTime UtcAdded { get; set; }
}
public class MyOutputCacheProvider: OutputCacheProvider
{
private readonly Dictionary<String, MyCacheItem> CacheDictionary = new Dictionary<String, MyCacheItem>();
public override object Get(string key)
{
lock(CacheDictionary)
{
if (!CacheDictionary.ContainsKey(key))
return null;
var Item = CacheDictionary[key];
// Item has expired?
if (Item.UtcExpiry < DateTime.UtcNow)
{
Remove(key);
return null;
}
return Item.ItemData;
}
}
public override object Add(string key, object entry, DateTime utcExpiry)
{
lock (CacheDictionary)
{
if (!CacheDictionary.ContainsKey(key))
{
MyCacheItem CacheItem = new MyCacheItem
{
ItemData = entry,
UtcExpiry = utcExpiry,
UtcAdded = DateTime.UtcNow
};
CacheDictionary.Add(key, CacheItem);
return CacheItem.ItemData;
}
var Item = CacheDictionary[key];
return Item.ItemData;
}
}
public override void Set(string key, object entry, DateTime utcExpiry)
{
lock (CacheDictionary)
{
if (!CacheDictionary.ContainsKey(key))
{
Add(key, entry, utcExpiry);
return;
}
CacheDictionary[key].ItemData = entry;
CacheDictionary[key].UtcExpiry = utcExpiry;
}
}
public override void Remove(string key)
{
lock (CacheDictionary)
{
if (!CacheDictionary.ContainsKey(key))
return;
CacheDictionary.Remove(key);
}
}
}
最后,web.config:
<system.web>
<caching>
<outputCache defaultProvider="MyCache">
<providers>
<add name="MyCache" type="MyApp.Namespace.MyOutputCacheProvider"/>
</providers>
</outputCache>
</caching>
</system.web>
答案 1 :(得分:1)
此问题已发布修补程序。有关详细信息,请参阅http://blogs.msdn.com/b/kwill/archive/2013/09/11/august-2013-windows-azure-guest-os-issue-with-system-runtime-caching-memorycache.aspx。
答案 2 :(得分:0)
所有内存中对象都将消失(内存中会话状态,缓存,静态值......),因为未处理的异常会破坏进程。对于ASP.Net,它意味着IIS(或dev服务器)将重新启动应用程序,并且您不会缓存数据。