Copied to clipboard

Flag this post as spam?

This post will be reported to the moderators as potential spam to be looked at


  • Pogo 6 posts 29 karma points
    Feb 17, 2015 @ 18:10
    Pogo
    0

    Umbraco 7.1.2 CacheHelper/HttpRequestCacheProvider multi threading Issue

    Hi, I've just ran into an issue while using "Umbraco.Web.Security.MembershipHelper.GetByUsername". I was getting the following error:

       Umbraco.Core.Cache.HttpRequestCacheProvider.get_ContextItems() +55
       Umbraco.Core.Cache.HttpRequestCacheProvider.get_WriteLock() +11
       Umbraco.Core.Cache.HttpRequestCacheProvider.GetCacheItem(String cacheKey, Func`1 getCacheItem) +83
       Umbraco.Core.Cache.CacheProviderExtensions.GetCacheItem(ICacheProvider provider, String cacheKey, Func`1 getCacheItem) +179
    

    My application relies heavily on async/await. Because of this its very rare that the user passes though the different layers off my application on the same Thread.

    Thus far Umbraco has been OK with this as long as I inject the current Umbraco/Application context into all of my dependencies rather than using the static Current properties, e.g. "UmbracoContext.Current" - this also makes my unit testing far easier.

    However the MembershipHelper.GetByUserName function relies on the HttpRequestCacheProvider. This class was changed as part of U4-4931 - fixing & refactoring to use the static method "HttpContext.Current" rather than having an HttpContext instance passed in during the construction of the object.

    This is causing me an issue because the thread calling "GetByUsername" is from the threadpool, not the one that started the request. I have managed to hack my own temporary fix to the issue (see below) but this is by no means an ideal solution. Basically before I inject the ApplicationContext into my classes I'm reflecting into the current ApplicationContext's CacheHelper instance, getting the HttpRequestCacheProvider instance and setting its private "_context" field.

            var current = ApplicationContext.Current;
    
            var cacheHelper = current.ApplicationCache;
    
            var responseCache = cacheHelper.GetType().GetField("_requestCache", BindingFlags.NonPublic | BindingFlags.Instance);
    
            var responseCacheInstance = responseCache.GetValue(cacheHelper);
    
            var contextField = responseCacheInstance.GetType().GetField("_context", BindingFlags.NonPublic | BindingFlags.Instance);
    
            var context = UmbracoContext.Current.HttpContext;
    
            contextField.SetValue(responseCacheInstance, context);
    

    Clearly this isn't an ideal workaround but it has resolved my issue. My question is can you guys start using your "// for unit tests" constructor again to avoid using the static method?

    Any help/input would be much appreciated!

  • Pogo 6 posts 29 karma points
    Feb 18, 2015 @ 09:42
    Pogo
    0

    Is there a better place for me to be asking/reporting these kinds of issues? Just dawned on me that this might be a little intense for the Forum.

  • Damiaan 442 posts 1302 karma points MVP 6x c-trib
    Dec 07, 2015 @ 15:36
    Damiaan
    0

    Hi Pogo,

    Yes there is another place. Issues can be posted on http://issues.umbraco.org

    Kind regards
    Damiaan

Please Sign in or register to post replies

Write your reply to:

Draft