public static void EnsureIsStarted(Key key,
                                           ICacheItemRecalculationStrategy recalculationStrategy,
                                           MethodInterceptionArgs args,
                                           ICache cache)
        {
            var keyString = key.ToString();
            Ensure.That<NHelpfulException.FrameworkExceptions.ArgumentException>(keyString.Length.IsLessThanOrEqualTo(260),
                                                              "key must be less than 260 characters long.");

            try
            {
                bool createdNew;
                var mutex = new Mutex(false, MutexPrefix + keyString, out createdNew);
                if (createdNew)
                {
                    if (cache[keyString].IsNotNull())
                        return;
                    //item already in cache, assume thread already started TODO: possibly log this as an error

                    ThreadPool.QueueUserWorkItem(
                        o => recalculationStrategy.RunRoutine(key, args, cache, mutex, args.Proceed));

                    //NOTE: mutex.ReleaseMutex(); is not called because the mutex is only expected to be released upon closure of the application
                }
            }
            catch (Exception)
            {
                //log exception
                throw;
            }
        }
Exemple #2
0
        /// <remarks>
        ///   Consider alternatives to instantiating instances 
        ///   of the specified types using Activator.CreateInstance.
        /// </remarks>
        public override void OnInvoke(MethodInterceptionArgs args)
        {
            Ensure.That<ArgumentNullException>(args.IsNotNull(), "args");

            _cache = (ICache) Activator.CreateInstance(_cacheType);
            _keyCreationStrategy = (IFriendlyNameCreationStrategy) Activator.CreateInstance(_keyCreationStrategyType);

            if (_recalculationStrategyType.IsNotNull())
            {
                _recalculationStrategy =
                    (ICacheItemRecalculationStrategy)
                    Activator.CreateInstance(_recalculationStrategyType, _durationToRecalculate);
            }

            var friendlyName = _keyCreationStrategy.GenerateFriendlyName(args);
            var key = _durationToStore == default(TimeSpan) //infer from the variables set, the key type to create?
                          ? new Key(DefaultCacheDuration, DefaultCacheExpirationType, friendlyName)
                          : new Key(_durationToStore, _storageStyle, _expirationType, friendlyName);
            object cacheItem;
            if ((cacheItem = _cache[key.ToString()]).IsNotNull())
            {
                args.ReturnValue = cacheItem;
            }
            else
            {
                args.Proceed();
                _cache.Add(key, args.ReturnValue);
                if (_recalculationStrategy.IsNotNull())
                    AsyncCacheItemRecalculator.EnsureIsStarted(key, _recalculationStrategy, args, _cache);
            }
        }