Ejemplo n.º 1
0
        /// <summary>
        /// 1.并发访问只会有一个真正的去请求,其它都在等结果。
        /// 2.成功一次后,以后都不会慢,至多数据几秒内不新鲜,因为数据过期后依然返回的是老数据,并且同时开了个线程在拿新数据。
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="action"></param>
        /// <param name="value"></param>
        /// <param name="expireMinutes">更新频率,此设置是用来保证新鲜度的,设置长或短不会影响性能!</param>
        /// <returns></returns>
        public static T Get <T>(CacheKeys key, Action action, ref T value, int expireMinutes)
        {
            bool hasError = false;

            if (key.NoCache()) //沒數據就嘗試去填充數據
            {
                var startTime = DateTime.Now;
                var isFirst   = Queue.TryAdd(key.GetName(), startTime); //第一個進來的填充就行,其它的等結果吧
                if (isFirst)
                {
                    Task.Factory.StartNew(() =>
                    {
                        try
                        {
                            if (key.NoCache())
                            {
                                action();
                                var cacheInfo = new CacheInfo
                                {
                                    Key        = key.GetName(),
                                    Desc       = key.GetDescription(),
                                    Count      = 1,
                                    CreateTime = DateTime.UtcNow,
                                    ExpireTime = DateTime.UtcNow.AddMinutes(expireMinutes),
                                    BuildTime  = (DateTime.Now - startTime)
                                };

                                HttpRuntime.Cache.Insert(cacheInfo.Key, cacheInfo, null, cacheInfo.ExpireTime.Value, Cache.NoSlidingExpiration, CacheItemPriority.NotRemovable, CacheOnRemovedCallback);
                                // PkgHelper.WritePerfLog("CacheHelper", (DateTime.Now - startTime).Milliseconds, key.GetName(), $"items:{1} ", "Offline.Service");
                            }
                        }
                        catch (Exception ex)
                        {
                            hasError     = true;
                            var director = AppDomain.CurrentDomain?.BaseDirectory?.ToLower() ?? string.Empty;
                            if (!string.IsNullOrWhiteSpace(director) && director.Contains("scheduler"))
                            {
                                // TASK 报这个错误是正常的,不记日志
                            }
                            else
                            {
                            }
                        }
                        finally
                        {
                            Queue.TryRemove(key.GetName(), out startTime);
                        }
                    });
                }
            }

            DateTime end = DateTime.Now.AddMinutes(5);

            while (DateTime.Now < end)
            {
                if (value != null || hasError)
                {
                    break;
                }
                Thread.Sleep(500);
            }
            return(value);
        }