public long SAdd <T>(string cacheKey, IList <T> cacheValues, TimeSpan?expiration = null) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNullAndCountGTZero(cacheValues, nameof(cacheValues)); var list = new List <RedisValue>(); foreach (var item in cacheValues) { list.Add(_serializer.Serialize(item)); } var len = _cache.SetAdd(cacheKey, list.ToArray()); if (expiration.HasValue) { _cache.KeyExpire(cacheKey, expiration.Value); } return(len); }
public CommandLine(string[] args) { ArgumentCheck.ParameterIsNotNull(args, nameof(args)); if (args.Length == 1 && (args[0] == "-?" || args[0] == "/?" || args[0] == "-h" || args[0] == "--help")) { PrintUsage(); return; } for (var i = args.Length - 1; i >= 0; i--) { arguments.Push(args[i]); } ParseArgs(); }
/// <summary> /// Gets all. /// </summary> /// <returns>The all.</returns> /// <param name="cacheKeys">Cache keys.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public IDictionary <string, CacheValue <T> > GetAll <T>(IEnumerable <string> cacheKeys)// where T : class { ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); var values = _memcachedClient.Get <T>(cacheKeys); var result = new Dictionary <string, CacheValue <T> >(); foreach (var item in values) { if (item.Value != null) { result.Add(item.Key, new CacheValue <T>(item.Value, true)); } else { result.Add(item.Key, CacheValue <T> .NoValue); } } return(result); }
/// <summary> /// Removes the specified cacheKey async. /// </summary> /// <returns>The async.</returns> /// <param name="cacheKey">Cache key.</param> public async Task RemoveAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); try { // distributed cache at first await _distributedCache.RemoveAsync(cacheKey); } catch (Exception ex) { LogMessage($"remove cache key [{cacheKey}] error", ex); } await _localCache.RemoveAsync(cacheKey); // send message to bus await _busAsyncWrap.ExecuteAsync(async() => await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } })); }
/// <summary> /// Removes all async. /// </summary> /// <returns>The all async.</returns> /// <param name="cacheKeys">Cache keys.</param> public async Task RemoveAllAsync(IEnumerable <string> cacheKeys) { ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); cacheKeys = cacheKeys.Select(x => BuildCacheKey(Name, x)); if (_options.EnableLogging) { _logger?.LogInformation($"RemoveAllAsync : cacheKeys = {string.Join(",", cacheKeys)}"); } var tasks = new List <Task>(); foreach (var key in cacheKeys.Distinct()) { var cacheKey = string.IsNullOrWhiteSpace(_name) ? key : key.Substring(Name.Length + 1, key.Length - Name.Length - 1); tasks.Add(RemoveAsync(cacheKey)); } await Task.WhenAll(tasks); }
/// <summary> /// Sets all async. /// </summary> /// <returns>The all async.</returns> /// <param name="values">Values.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public async Task SetAllAsync <T>(IDictionary <string, T> values, TimeSpan expiration) where T : class { ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); ArgumentCheck.NotNullAndCountGTZero(values, nameof(values)); var tran = _cache.BeginTransaction(); var tasks = new List <Task <int> >(); foreach (var item in values) { tasks.Add(_cache.ExecuteAsync(ConstSQL.SETSQL, new { cachekey = item.Key, cachevalue = Newtonsoft.Json.JsonConvert.SerializeObject(item.Value), expiration = expiration.Ticks / 10000000 }, tran)); } await Task.WhenAll(tasks); tran.Commit(); }
public static void RemoveStructureChangedEventHandler( AutomationElement element, StructureChangedEventHandler eventHandler) { ArgumentCheck.NotNull(element, "element"); ArgumentCheck.NotNull(eventHandler, "eventHandler"); if (element == AutomationElement.RootElement) { foreach (var source in SourceManager.GetAutomationSources()) { source.RemoveStructureChangedEventHandler( null, eventHandler); } } else { var source = element.SourceElement.AutomationSource; source.RemoveStructureChangedEventHandler( element.SourceElement, eventHandler); } }
/// <summary> /// Adds the EasyCaching response caching. /// </summary> /// <param name="services">Services.</param> /// <param name="action">Configure response caching settings.</param> /// <param name="name">The provider name that will use to store the response.</param> public static IServiceCollection AddEasyCachingResponseCaching( this IServiceCollection services , Action <ResponseCachingOptions> action , string name ) { ArgumentCheck.NotNull(services, nameof(services)); services.Configure(action); services.TryAddSingleton <IResponseCachingPolicyProvider, ResponseCachingPolicyProvider>(); services.TryAddSingleton <IResponseCachingKeyProvider, ResponseCachingKeyProvider>(); services.TryAddSingleton <ObjectPoolProvider, DefaultObjectPoolProvider>(); services.AddSingleton <IResponseCache, EasyCachingResponseCache>(x => { var factory = x.GetRequiredService <IEasyCachingProviderFactory>(); return(new EasyCachingResponseCache(name, factory)); }); return(services); }
/// <summary> /// Set the specified cacheKey, cacheValue and expiration. /// </summary> /// <returns>The set.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="cacheValue">Cache value.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public override void BaseSet <T>(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNull(cacheValue, nameof(cacheValue)); ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); if (MaxRdSecond > 0) { var addSec = new Random().Next(1, MaxRdSecond); expiration.Add(new TimeSpan(0, 0, addSec)); } var exp = expiration.Ticks / 10000000; _cache.Upsert(new CacheItem { cachekey = cacheKey, name = _name, cachevalue = Newtonsoft.Json.JsonConvert.SerializeObject(cacheValue), expiration = expiration.Ticks / 10000000 }); }
/// <summary> /// Remove the specified cacheKey. /// </summary> /// <param name="cacheKey">Cache key.</param> public void Remove(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); try { // distributed cache at first _distributedCache.Remove(cacheKey); } catch (Exception ex) { _logger?.LogError(ex, "remove cache key [{0}] error", cacheKey); } _localCache.Remove(cacheKey); // send message to bus _bus.Publish(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); }
/// <summary> /// Existses the specified cacheKey async. /// </summary> /// <returns>The async.</returns> /// <param name="cacheKey">Cache key.</param> public async Task <bool> ExistsAsync(string cacheKey) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); bool flag; try { flag = await _distributedCache.ExistsAsync(cacheKey); return(flag); } catch (Exception ex) { _logger?.LogError(ex, "Check cache key [{0}] exists error", cacheKey); } flag = await _localCache.ExistsAsync(cacheKey); return(flag); }
/// <summary> /// Gets the specified cacheKey, dataRetriever and expiration async. /// </summary> /// <returns>The async.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="dataRetriever">Data retriever.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public async Task <CacheValue <T> > GetAsync <T>(string cacheKey, Func <Task <T> > dataRetriever, TimeSpan expiration) where T : class { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); var list = await _cache.QueryAsync <string>(ConstSQL.GETSQL, new { cachekey = cacheKey }); var dbResult = list.FirstOrDefault(); if (!string.IsNullOrWhiteSpace(dbResult)) { if (_options.EnableLogging) { _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); } return(new CacheValue <T>(Newtonsoft.Json.JsonConvert.DeserializeObject <T>(dbResult), true)); } var item = await dataRetriever?.Invoke(); if (item != null) { await SetAsync(cacheKey, item, expiration); return(new CacheValue <T>(item, true)); } else { if (_options.EnableLogging) { _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); } return(CacheValue <T> .NoValue); } }
/// <summary> /// Tries the set. /// </summary> /// <returns><c>true</c>, if set was tryed, <c>false</c> otherwise.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="cacheValue">Cache value.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public bool TrySet <T>(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); bool distributedError = false; bool flag = false; try { flag = _distributedCache.TrySet(cacheKey, cacheValue, expiration); } catch (Exception ex) { distributedError = true; _logger?.LogError(ex, "tryset cache key [{0}] error", cacheKey); } if (flag && !distributedError) { // When we TrySet succeed in distributed cache, we should Set this cache to local cache. // It's mainly to prevent the cache value was changed _localCache.Set(cacheKey, cacheValue, expiration); } // distributed cache occur error, have a try with local cache if (distributedError) { flag = _localCache.TrySet(cacheKey, cacheValue, expiration); } if (flag) { // Here should send message to bus due to cache was set successfully. _bus.Publish(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } }); } return(flag); }
/// <summary> /// Tries the set async. /// </summary> /// <returns>The set async.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="cacheValue">Cache value.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public async Task <bool> TrySetAsync <T>(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); bool distributedError = false; bool flag = false; try { flag = await _distributedCache.TrySetAsync(cacheKey, cacheValue, expiration); } catch (Exception ex) { distributedError = true; LogMessage($"tryset cache key [{cacheKey}] error", ex); } if (flag && !distributedError) { // When we TrySet succeed in distributed cache, we should Set this cache to local cache. // It's mainly to prevent the cache value was changed await _localCache.SetAsync(cacheKey, cacheValue, expiration); } // distributed cache occur error, have a try with local cache if (distributedError) { flag = await _localCache.TrySetAsync(cacheKey, cacheValue, expiration); } if (flag) { // Here should send message to bus due to cache was set successfully. await _busAsyncWrap.ExecuteAsync(async() => await _bus.PublishAsync(_options.TopicName, new EasyCachingMessage { Id = _cacheId, CacheKeys = new string[] { cacheKey } })); } return(flag); }
public static void RegisterClientSideProviderAssembly(AssemblyName assemblyName) { ArgumentCheck.NotNull(assemblyName, "assemblyName"); Assembly assembly = null; // TODO, wrap exception messages into Catalog.GetString try { assembly = Assembly.Load(assemblyName); } catch (FileNotFoundException) { throw new ProxyAssemblyNotLoadedException( string.Format("'{0}' assembly not found.", assemblyName)); } string typeName = assemblyName.Name + ".UIAutomationClientSideProviders"; Type type = assembly.GetType(typeName); if (type == null) { throw new ProxyAssemblyNotLoadedException( string.Format("Cannot find type {0} in assembly {1}", typeName, assemblyName)); } FieldInfo field = type.GetField("ClientSideProviderDescriptionTable", BindingFlags.Public | BindingFlags.Static); if ((field == null) || (field.FieldType != typeof(ClientSideProviderDescription[]))) { throw new ProxyAssemblyNotLoadedException( string.Format("Cannot find Register method on type {0} in assembly {1}", typeName, assemblyName)); } var description = field.GetValue(null) as ClientSideProviderDescription []; if (description != null) { ClientSettings.RegisterClientSideProviders(description); } }
/// <summary> /// Gets the specified cacheKey, dataRetriever and expiration async. /// </summary> /// <returns>The async.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="dataRetriever">Data retriever.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public async Task <CacheValue <T> > GetAsync <T>(string cacheKey, Func <Task <T> > dataRetriever, TimeSpan expiration) where T : class { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); var result = await _cache.StringGetAsync(cacheKey); if (!result.IsNull) { CacheStats.OnHit(); if (_options.EnableLogging) { _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); } var value = _serializer.Deserialize <T>(result); return(new CacheValue <T>(value, true)); } CacheStats.OnMiss(); if (_options.EnableLogging) { _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); } var item = await dataRetriever?.Invoke(); if (item != null) { await SetAsync(cacheKey, item, expiration); return(new CacheValue <T>(item, true)); } else { return(CacheValue <T> .NoValue); } }
// ---------------------------------------------------------------------- public void Register(ILoggerListener loggerListener, string context) { if (loggerListener == null) { throw new ArgumentNullException("loggerListener"); } string checkedContext = ArgumentCheck.NonemptyTrimmedString(context, "context"); lock ( listenerListsByContext ) { List <ILoggerListener> contextListeners; if (!listenerListsByContext.TryGetValue(checkedContext, out contextListeners)) { contextListeners = new List <ILoggerListener>(5); listenerListsByContext.Add(checkedContext, contextListeners); } lock ( contextListeners ) { contextListeners.Add(loggerListener); } } } // Register
public override int Query(FormM form, DFDictionary entity, DataGridVM vm, int start, int limit, ref string message) { if (IsEmptyQuery(entity)) { return(EmptyQuery(vm)); } ArgumentCheck.CheckMustInput(entity, "TableName"); var tableName = entity["TableName"]; List <VM_ColumnMetadata> list = null; // 如果是客户端点击查询按钮,或者回传回的数据没有客户端数据 IDBHelper dbHelper; using (var db = Pub.DB) { dbHelper = DBHelper.GetDBHelper(db); } list = dbHelper.LoadColumns(tableName); vm.results = list.Count; vm.rows = Merge(tableName, list.Skip(start).Take(limit).ToList()); return(DFPub.EXECUTE_SUCCESS); }
// ---------------------------------------------------------------------- public void Register(ILoggerListener loggerListener, string context) { if (loggerListener == null) { throw new ArgumentNullException("loggerListener"); } string checkedContext = ArgumentCheck.NonemptyTrimmedString(context, "context"); lock (listenerListsByContext) { ArrayList contextListeners = listenerListsByContext[checkedContext] as ArrayList; if (contextListeners == null) { contextListeners = new ArrayList(5); listenerListsByContext.Add(checkedContext, contextListeners); } lock (contextListeners) { contextListeners.Add(loggerListener); } } } // Register
/// <summary> /// Gets the by prefix. /// </summary> /// <returns>The by prefix.</returns> /// <param name="prefix">Prefix.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public IDictionary <string, CacheValue <T> > GetByPrefix <T>(string prefix) where T : class { ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); var map = new Dictionary <string, CacheValue <T> >(); if (_options.EnableLogging) { _logger?.LogInformation($"GetByPrefix : prefix = {prefix}"); } var keys = _cacheKeys.Where(x => x.StartsWith(prefix.Trim(), StringComparison.OrdinalIgnoreCase)); if (keys.Any()) { foreach (var item in keys) { map[item] = this.Get <T>(item); } } return(map); }
/// <summary> /// Removes cached item by cachekey's prefix async. /// </summary> /// <returns>The by prefix async.</returns> /// <param name="prefix">Prefix.</param> public async Task RemoveByPrefixAsync(string prefix) { ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); var keys = _cacheKeys.Where(x => x.StartsWith(prefix.Trim(), StringComparison.OrdinalIgnoreCase)); if (_options.EnableLogging) { _logger?.LogInformation($"RemoveByPrefixAsync : prefix = {prefix}"); } if (keys.Any()) { var tasks = new List <Task>(); foreach (var item in keys) { tasks.Add(RemoveAsync(item)); } await Task.WhenAll(tasks); } }
public override void BaseRemoveAll(IEnumerable<string> cacheKeys) { ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); foreach (string key in cacheKeys) { if (string.IsNullOrWhiteSpace(key)) continue; var path = GetRawPath(key); if (!File.Exists(path)) { continue; } if (DeleteFileWithRetry(path)) { _cacheKeysMap.TryRemove(key, out _); } } }
/// <summary> /// Gets all async. /// </summary> /// <returns>The all async.</returns> /// <param name="cacheKeys">Cache keys.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public override async Task <IDictionary <string, CacheValue <T> > > BaseGetAllAsync <T>(IEnumerable <string> cacheKeys) { ArgumentCheck.NotNullAndCountGTZero(cacheKeys, nameof(cacheKeys)); var values = await _memcachedClient.GetAsync <T>(cacheKeys); var result = new Dictionary <string, CacheValue <T> >(); foreach (var item in values) { if (item.Value != null) { result.Add(item.Key, new CacheValue <T>(item.Value, true)); } else { result.Add(item.Key, CacheValue <T> .NoValue); } } return(result); }
public List <bool> StringSetBit(string cacheKey, IEnumerable <long> offsets, bool value) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); var results = new Task <bool> [offsets.Count()]; var batch = _redisDb.CreateBatch(); var index = 0; foreach (var position in offsets) { results[index] = batch.StringSetBitAsync(cacheKey, position, value); index++; } batch.Execute(); if (!Task.WaitAll(results, TimeoutMilliseconds)) { throw new TimeoutException(); } return(results.Select(r => r.Result).ToList()); }
public static async Task <bool> SafedUnLockAsync(this IDatabase redisDb, string cacheKey, string lockValue) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNullOrWhiteSpace(lockValue, nameof(lockValue)); var lockKey = GetLockKey(cacheKey); AutoDelayTimers.Instance.CloseTimer(lockKey); var script = @"local invalue = @value local currvalue = redis.call('get',@key) if(invalue==currvalue) then redis.call('del',@key) return 1 else return 0 end"; var parameters = new { key = lockKey, value = lockValue }; var prepared = LuaScript.Prepare(script); var result = (int)await redisDb.ScriptEvaluateAsync(prepared, parameters); return(result == 1); }
/// <summary> /// Removes the by prefix async. /// </summary> /// <returns>The by prefix async.</returns> /// <param name="prefix">Prefix.</param> public override async Task BaseRemoveByPrefixAsync(string prefix) { ArgumentCheck.NotNullOrWhiteSpace(prefix, nameof(prefix)); prefix = this.HandlePrefix(prefix); if (_options.EnableLogging) { _logger?.LogInformation($"RemoveByPrefixAsync : prefix = {prefix}"); } var redisKeys = this.SearchRedisKeys(prefix); var tasks = new List <Task <long> >(); foreach (var item in redisKeys) { tasks.Add(_cache.DelAsync(item)); } await Task.WhenAll(tasks); }
/// <summary> /// Gets the specified cacheKey, dataRetriever and expiration async. /// </summary> /// <returns>The async.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="dataRetriever">Data retriever.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public async Task <CacheValue <T> > GetAsync <T>(string cacheKey, Func <Task <T> > dataRetriever, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); var result = await _memcachedClient.GetValueAsync <T>(this.HandleCacheKey(cacheKey)); if (result != null) { CacheStats.OnHit(); if (_options.EnableLogging) { _logger?.LogInformation($"Cache Hit : cachekey = {cacheKey}"); } return(new CacheValue <T>(result, true)); } CacheStats.OnMiss(); if (_options.EnableLogging) { _logger?.LogInformation($"Cache Missed : cachekey = {cacheKey}"); } var item = await dataRetriever?.Invoke(); if (item != null) { await this.SetAsync(cacheKey, item, expiration); return(new CacheValue <T>(item, true)); } else { return(CacheValue <T> .NoValue); } }
/// <summary> /// Get the specified cacheKey, dataRetriever and expiration. /// </summary> /// <returns>The get.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="dataRetriever">Data retriever.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public override CacheValue <T> BaseGet <T>(string cacheKey, Func <T> dataRetriever, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); var result = BaseGet <T>(cacheKey); if (result.HasValue) { return(result); } var item = dataRetriever(); if (item != null || _options.CacheNulls) { Set(cacheKey, item, expiration); result = new CacheValue <T>(item, true); } return(result); }
/// <summary> /// Tries the set. /// </summary> /// <returns><c>true</c>, if set was tryed, <c>false</c> otherwise.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="cacheValue">Cache value.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public override bool BaseTrySet <T>(string cacheKey, T cacheValue, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNull(cacheValue, nameof(cacheValue), _options.CacheNulls); ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); if (MaxRdSecond > 0) { var addSec = new Random().Next(1, MaxRdSecond); expiration.Add(new TimeSpan(0, 0, addSec)); } var rows = _cache.Execute(ConstSQL.TRYSETSQL, new { cachekey = cacheKey, name = _name, cachevalue = Newtonsoft.Json.JsonConvert.SerializeObject(cacheValue), expiration = expiration.Ticks / 10000000 }); return(rows > 0); }
/// <summary> /// Gets the specified cacheKey, dataRetriever and expiration async. /// </summary> /// <returns>The async.</returns> /// <param name="cacheKey">Cache key.</param> /// <param name="dataRetriever">Data retriever.</param> /// <param name="expiration">Expiration.</param> /// <typeparam name="T">The 1st type parameter.</typeparam> public override async Task <CacheValue <T> > BaseGetAsync <T>(string cacheKey, Func <Task <T> > dataRetriever, TimeSpan expiration) { ArgumentCheck.NotNullOrWhiteSpace(cacheKey, nameof(cacheKey)); ArgumentCheck.NotNegativeOrZero(expiration, nameof(expiration)); var result = await BaseGetAsync <T>(cacheKey); if (result.HasValue) { return(result); } var flag = await _memcachedClient.StoreAsync(Enyim.Caching.Memcached.StoreMode.Add, this.HandleCacheKey($"{cacheKey}_Lock"), 1, TimeSpan.FromMilliseconds(_options.LockMs)); if (!flag) { await Task.Delay(_options.SleepMs); return(await GetAsync(cacheKey, dataRetriever, expiration)); } var item = await dataRetriever(); if (item != null || _options.CacheNulls) { await this.SetAsync(cacheKey, item, expiration); await _memcachedClient.RemoveAsync(this.HandleCacheKey($"{cacheKey}_Lock")); return(new CacheValue <T>(item, true)); } else { await _memcachedClient.RemoveAsync(this.HandleCacheKey($"{cacheKey}_Lock")); return(CacheValue <T> .NoValue); } }