在finally块中释放时放弃了AbandonedMutexException

时间:2018-11-16 10:59:19

标签: c# mutex

我有一个在缓存中存储大列表的应用程序。为了防止多个用户同时填充此缓存,我使用了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)

1 个答案:

答案 0 :(得分:1)

您应该使用单个互斥锁,而不是为每个函数调用声明一个新的互斥锁。也许在此函数所在的类的范围内声明一个静态互斥锁,然后根据需要等待/释放。检查此页面上的示例:

https://docs.microsoft.com/en-us/dotnet/api/system.threading.mutex?view=netframework-4.7.2