我有一个在缓存中存储大列表的应用程序。为了防止多个用户同时填充此缓存,我使用了Mutex。但是,偶尔会出现错误:
System.Threading.AbandonedMutexException:由于放弃了互斥锁,所以等待已完成。
您可能会争辩说我忘记发布Mutex,但该发布位于Final块中,因此它应始终发布。下面的代码如何导致AbandonedMutexException? “ mutex.ReleaseMutex”应该总是被触发。
public static List<Objects.SearchListItem> GetActiveCwPropertyListItemsByCwPropertyAndCulture(CwProperty cwProperty, string cultureCode)
{
var cacheKey = "GetActiveCwPropertyListItemsByCwPropertyAndCulture_" + cwProperty.Guid + "_" + cultureCode;
var mutex = new Mutex(true, cacheKey);
mutex.WaitOne();
try
{
var cachedValue = HttpRuntime.Cache[cacheKey];
if (cachedValue != null) return (List<Objects.SearchListItem>)cachedValue;
var value = new List<Objects.SearchListItem>();
var dr = new CwDbAccess(System.Data.CommandType.StoredProcedure, "CwPropertyListItemPart_LoadByCwProperty");
try
{
dr.ExecuteReader();
while (dr.MyReader.Read())
{
value.Add(new Objects.SearchListItem
{
Name = Utils.ProperCase(dr.MyReader["Name"].ToString()),
Key = dr.MyReader["CwPropertyListItem_Guid"].ToString(),
IsAlias = false
});
}
}
catch (Exception ex)
{
CwLogging.LogException("Caching.ListItems.GetActiveCwPropertyListItemsByCwPropertyAndCulture", ex, ExceptionLevel.Urgent);
}
finally
{
dr.Close();
}
var keys = new List<string>();
AddDependency("CwSiteClusterKey_" + cwProperty.CachedCwEntity.CwSiteClusterGuid, keys);
AddDependency("CwPropertyKey_" + cwProperty.Guid, keys);
HttpRuntime.Cache.Insert(cacheKey, value, new CacheDependency(null, keys.ToArray()), Cache.NoAbsoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
return value;
}
catch
{
throw;
}
finally
{
mutex.ReleaseMutex();
}
}
完整的堆栈跟踪为:
System.Threading.AbandonedMutexException:由于放弃了互斥,等待已完成。 在System.Threading.WaitHandle.ThrowAbandonedMutexException() 在System.Threading.WaitHandle.InternalWaitOne处(SafeHandle waitableSafeHandle,Int64毫秒超时,布尔值hasThreadAffinity,布尔值exitContext) 在System.Threading.WaitHandle.WaitOne处(Int32毫秒超时,布尔值exitContext) 在Common.Caching.ListItems.GetActiveCwPropertyListItemsByCwPropertyAndCulture(CwProperty cwProperty,字符串cultureCode) 在Model.SearchFacet.GetAllSearchListItems(CwContext cwContext) 在Common.Search.SqlFacets.RetrieveSqlFacetsByGroup(CwEntity cwEntity,NameValueCollectionstoredRequestForm,SqlFacetsContainer sqlFacets,SearchFacetGroupCollection组,SearchTemplate searchTemplate,CwContext cwContext) 在Common.Search.SqlFacets.RetrieveSqlFacets(CwEntity cwEntity,NameValueCollectionstoredRequestForm,CwContext cwContext,SearchResultViewType searchResultViewType) 在Common.Caching.SqlFacets.GetSqlFacets(字符串哈希,NameValueCollectionstoredRequestForm,CwEntity cwEntity,CwContext cwContext,SearchResultViewType searchResultViewType) 位于C:\ Projects \ Compareware \ Compareware.WebApp \ Ui \ Pages \ SearchPage.cs:line 454中的Compareware_WebApp.Ui.Pages.SearchPage.AppendSearchAndResults(StringBuilder sb) 在C:\ Projects \ Compareware \ Compareware.WebApp \ Ui \ Pages \ SearchPage.cs:line 310中的Compareware_WebApp.Ui.Pages.SearchPage.get_MainContent() 在ASP.default_aspx .__ RenderContent2(HtmlTextWriter __w,控制parameterContainer) 在System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection子级) 在System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) 在System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection子级) 在System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) 在ASP.masters_site_master .__ RenderForm1(HtmlTextWriter __w,控制parameterContainer) 在System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection子级) 在System.Web.UI.HtmlControls.HtmlForm.RenderChildren(HtmlTextWriter writer) 在System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) 在System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) 在System.Web.UI.HtmlControls.HtmlForm.RenderControl(HtmlTextWriter writer) 在ASP.masters_site_master .__ RenderBody(HtmlTextWriter __w,控制parameterContainer) 在System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection子级) 在System.Web.UI.HtmlControls.HtmlContainerControl.Render(HtmlTextWriter writer) 在System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) 在ASP.masters_site_master .__ Render__control1(HtmlTextWriter __w,控制parameterContainer) 在System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection子级) 在System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) 在System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection子级) 在System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) 在System.Web.UI.Control.RenderChildrenInternal(HtmlTextWriter writer,ICollection子级) 在System.Web.UI.Page.Render(HtmlTextWriter writer) 在System.Web.UI.Control.RenderControlInternal(HtmlTextWriter writer,ControlAdapter适配器) 在System.Web.UI.Page.ProcessRequestMain(Boolean includeStagesBeforeAsyncPoint,Boolean includeStagesAfterAsyncPoint)
答案 0 :(得分:1)
您应该使用单个互斥锁,而不是为每个函数调用声明一个新的互斥锁。也许在此函数所在的类的范围内声明一个静态互斥锁,然后根据需要等待/释放。检查此页面上的示例:
https://docs.microsoft.com/en-us/dotnet/api/system.threading.mutex?view=netframework-4.7.2