游戏列表异步实验
This commit is contained in:
parent
1fb5621af7
commit
ea1fc8a322
|
|
@ -56,7 +56,7 @@ namespace CloudGaming.Api.Controllers
|
|||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[RedisCache(2, 2, 0)]
|
||||
public GameInfoDto GetGameInfo([FromQuery] string gameId)
|
||||
public Task<GameInfoDto> GetGameInfo([FromQuery] string gameId)
|
||||
{
|
||||
GameBLL gamebll = new GameBLL(this.ServiceProvider);
|
||||
return gamebll.GetGameInfo(gameId);
|
||||
|
|
@ -68,7 +68,7 @@ namespace CloudGaming.Api.Controllers
|
|||
/// <returns></returns>
|
||||
[HttpGet]
|
||||
[RedisCache(0, 5, 0)]
|
||||
public List<GameListDto> GameRecommendations([FromQuery] string? gameId)
|
||||
public Task<List<GameListDto>> GameRecommendations([FromQuery] string? gameId)
|
||||
{
|
||||
|
||||
GameBLL gamebll = new GameBLL(this.ServiceProvider);
|
||||
|
|
|
|||
|
|
@ -95,7 +95,7 @@ namespace CloudGaming.Code.Cache
|
|||
get
|
||||
{
|
||||
|
||||
return GameEntityCache?.DataList ?? new List<GameInfo>();
|
||||
return GameEntityCache?.DataListAsync.Result;// ?? new List<GameInfo>();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -10,6 +10,8 @@ using CloudGaming.GameModel.Db.Db_Game;
|
|||
using HuanMeng.DotNetCore.CacheHelper;
|
||||
using HuanMeng.DotNetCore.Redis;
|
||||
|
||||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using Org.BouncyCastle.Utilities.Collections;
|
||||
|
|
@ -24,37 +26,63 @@ namespace CloudGaming.Code.Cache.Special
|
|||
/// <summary>
|
||||
/// 游戏缓存表
|
||||
/// </summary>
|
||||
public class GameEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) : CommonDataEntityCache<GameInfo>(GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7)
|
||||
public class GameEntityCache(DAO dao, IDatabase database, IMapper mapper, AppConfig appConfig) :
|
||||
CommonDataEntityCacheAsync<GameInfo>(GameEntityCache.SemaphoreSlim, 60 * 60 * 24)
|
||||
//CommonDataEntityCache<GameInfo>(GameEntityCache.GameEntityCacheLock, 60 * 60 * 24 * 7)
|
||||
{
|
||||
public static object GameEntityCacheLock;
|
||||
|
||||
/// <summary>
|
||||
/// 异步锁
|
||||
/// </summary>
|
||||
public static SemaphoreSlim SemaphoreSlim = new SemaphoreSlim(1, 1);
|
||||
/// <summary>
|
||||
/// 内存key
|
||||
/// </summary>
|
||||
public override string key => $"{appConfig.Identifier}:game:gameInfo";
|
||||
|
||||
/// <summary>
|
||||
/// 缓存锁key
|
||||
/// </summary>
|
||||
public string locaKey => $"lock:gameInfo";
|
||||
/// <summary>
|
||||
/// redis 缓存key
|
||||
/// </summary>
|
||||
public string RedisKey => $"cache:game:gameInfo";
|
||||
/// <summary>
|
||||
/// 缓存时间
|
||||
/// </summary>
|
||||
public const int CacheHoursTime = 10;
|
||||
|
||||
public override List<GameInfo> GetDataList()
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 游戏数据
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public override async Task<List<GameInfo>> GetDataListAsync()
|
||||
{
|
||||
var gameCbtList = dao.DaoPhone.Context.T_GameCBT.AsNoTracking().Where(it => it.IsOnline).ToList() ?? new List<T_GameCBT>();
|
||||
var gameListDict = dao.DaoGame.Context.T_Game_List.AsNoTracking().ToDictionary(g => g.GameId);
|
||||
var gameChildList = dao.DaoGame.Context.T_Game_ChildList.AsNoTracking().ToList();
|
||||
|
||||
var gameTypesDict = dao.DaoGame.Context.T_Game_Types.AsNoTracking().ToDictionary(type => type.TypeId);
|
||||
var gameTagsDict = dao.DaoGame.Context.T_Game_Tags.AsNoTracking().ToDictionary(tag => tag.TagId);
|
||||
//游戏分享头像
|
||||
var gameUserShare = dao.DaoGame.Context.T_Game_UserShare.AsNoTracking().GroupBy(it => it.GameId).ToDictionary(it => it.Key, it => it.Last().NickName);
|
||||
var appConfig = dao.DaoExt.Context.T_App_Config.AsNoTracking().Where(it => it.ConfigType == 3).ToList();
|
||||
var gameCbtList = await dao.DaoPhone.Context.T_GameCBT.AsNoTracking().Where(it => it.IsOnline).ToListAsync() ?? new List<T_GameCBT>();
|
||||
//游戏列表
|
||||
var gameListDict = await dao.DaoGame.Context.T_Game_List.AsNoTracking().ToDictionaryAsync(g => g.GameId);
|
||||
//游戏标签、分类关联
|
||||
var gameChildList = await dao.DaoGame.Context.T_Game_ChildList.AsNoTracking().ToListAsync();
|
||||
//游戏分类
|
||||
var gameTypesDict = await dao.DaoGame.Context.T_Game_Types.AsNoTracking().ToDictionaryAsync(type => type.TypeId);
|
||||
//标签
|
||||
var gameTagsDict = await dao.DaoGame.Context.T_Game_Tags.AsNoTracking().ToDictionaryAsync(tag => tag.TagId);
|
||||
//游戏用户分享
|
||||
var gameUserShare = await dao.DaoGame.Context.T_Game_UserShare.AsNoTracking().GroupBy(it => it.GameId).ToDictionaryAsync(it => it.Key, it => it.Last().NickName);
|
||||
//游戏配置
|
||||
var appConfig = await dao.DaoExt.Context.T_App_Config.AsNoTracking().Where(it => it.ConfigType == 3).ToListAsync();
|
||||
//统一消耗配置
|
||||
var config = appConfig.GetAppConfig(3, 1, null);
|
||||
var defaultConsumeDiamondNumHour = 0;
|
||||
if (!string.IsNullOrEmpty(config?.ConfigValue))
|
||||
{
|
||||
int.TryParse(config?.ConfigValue, out defaultConsumeDiamondNumHour);
|
||||
}
|
||||
//var lorem = new Bogus.DataSets.Lorem(locale: "zh_CN");
|
||||
//生成用户昵称
|
||||
var faker = new Faker("zh_CN");
|
||||
//f.r
|
||||
|
||||
//lorem.
|
||||
//组装游戏
|
||||
var gameInfos = gameCbtList
|
||||
.Where(gameCbt => gameListDict.ContainsKey(gameCbt.GameId))
|
||||
.Select(gameCbt =>
|
||||
|
|
@ -76,7 +104,6 @@ namespace CloudGaming.Code.Cache.Special
|
|||
gameInfo.ConsumeDiamondNumHour = defaultConsumeDiamondNumHour;
|
||||
}
|
||||
|
||||
|
||||
if (gameInfo.ConsumeDiamondNumHour > 0)
|
||||
{
|
||||
gameInfo.GameDetailsofCharges = $"游戏资费:游玩按分钟计费,{gameInfo.ConsumeDiamondNumHour}钻石/小时。";
|
||||
|
|
@ -92,85 +119,93 @@ namespace CloudGaming.Code.Cache.Special
|
|||
return gameInfos;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public override List<GameInfo> DataList
|
||||
|
||||
public override Task<List<GameInfo>> DataListAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
start:
|
||||
if (_dataList != null) return _dataList;
|
||||
if (_dataList != null) return Task.FromResult(_dataList);
|
||||
|
||||
|
||||
var tempDataList = MemoryCacheHelper.GetCache<List<GameInfo>>(key);
|
||||
if (tempDataList != null)
|
||||
{
|
||||
_dataList = tempDataList;
|
||||
return _dataList;
|
||||
return Task.FromResult(_dataList);
|
||||
}
|
||||
|
||||
long hashLength = database.HashLength(RedisKey);
|
||||
if (hashLength > 0)
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
var hashEntries = database.HashGetAll(RedisKey);
|
||||
var list = hashEntries
|
||||
.Where(entry => !string.IsNullOrEmpty(entry.Value))
|
||||
.Select(entry => JsonConvert.DeserializeObject<GameInfo>(entry.Value))
|
||||
.ToList();
|
||||
start:
|
||||
long hashLength = await database.HashLengthAsync(RedisKey);
|
||||
if (hashLength > 0)
|
||||
{
|
||||
var hashEntries = await database.HashGetAllAsync(RedisKey);
|
||||
var list = hashEntries
|
||||
.Where(entry => !string.IsNullOrEmpty(entry.Value))
|
||||
.Select(entry => JsonConvert.DeserializeObject<GameInfo>(entry.Value))
|
||||
.ToList();
|
||||
|
||||
MemoryCacheHelper.SetCache(key, list, 10);
|
||||
_dataList = list;
|
||||
MemoryCacheHelper.SetCache(key, list, TimeSpan.FromHours(CacheHoursTime));
|
||||
_dataList = list;
|
||||
return _dataList;
|
||||
}
|
||||
|
||||
if (!database.StringSetLock(locaKey, "1", 5))
|
||||
{
|
||||
await Task.Delay(50);
|
||||
goto start;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
tempDataList ??= await GetDataListAsync();
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, TimeSpan.FromHours(CacheHoursTime));
|
||||
var serializedGameInfos = tempDataList
|
||||
.Select(info => new HashEntry($"gameInfo:{info.GameId}", JsonConvert.SerializeObject(info)))
|
||||
.ToArray();
|
||||
await database.HashSetAsync(RedisKey, serializedGameInfos);
|
||||
// 设置过期时间为1天
|
||||
await database.KeyExpireAsync(RedisKey, TimeSpan.FromDays(1));
|
||||
_dataList = tempDataList;
|
||||
}
|
||||
finally
|
||||
{
|
||||
database.KeyDelete(locaKey);
|
||||
}
|
||||
return _dataList;
|
||||
}
|
||||
});
|
||||
|
||||
if (!database.StringSetLock(locaKey, "1", 5))
|
||||
{
|
||||
goto start;
|
||||
}
|
||||
|
||||
tempDataList ??= GetDataList();
|
||||
var serializedGameInfos = tempDataList
|
||||
.Select(info => new HashEntry($"gameInfo:{info.GameId}", JsonConvert.SerializeObject(info)))
|
||||
.ToArray();
|
||||
database.HashSet(RedisKey, serializedGameInfos);
|
||||
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, 60 * 60);
|
||||
_dataList = tempDataList;
|
||||
database.KeyDelete(locaKey);
|
||||
return _dataList;
|
||||
}
|
||||
}
|
||||
|
||||
//public Task<List<GameInfo>> DataListAsync
|
||||
//{
|
||||
// get
|
||||
// {
|
||||
|
||||
// return new List<GameInfo>();
|
||||
// }
|
||||
//}
|
||||
private Dictionary<string, GameInfo> gameInfoDic;
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 游戏详情
|
||||
/// </summary>
|
||||
public Dictionary<string, GameInfo> GameInfoDic
|
||||
public Task<Dictionary<string, GameInfo>> GameInfoAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
if (gameInfoDic == null)
|
||||
if (gameInfoDic != null)
|
||||
{
|
||||
gameInfoDic = DataList.ToDictionary(it => it.GameId);
|
||||
return Task.FromResult(gameInfoDic);
|
||||
}
|
||||
return gameInfoDic;
|
||||
return Task.Run(async () => { gameInfoDic = (await DataListAsync).ToDictionary(it => it.GameId); return gameInfoDic; });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取游戏详情
|
||||
/// </summary>
|
||||
/// <param name="gameId"></param>
|
||||
/// <returns></returns>
|
||||
public GameInfo? this[string? gameId]
|
||||
public Task<GameInfo?> this[string? gameId]
|
||||
{
|
||||
get
|
||||
{
|
||||
|
|
@ -178,15 +213,11 @@ namespace CloudGaming.Code.Cache.Special
|
|||
{
|
||||
return null;
|
||||
}
|
||||
return GameInfoDic[gameId] ?? null;
|
||||
return Task.Run(async () => (await GameInfoAsync)[gameId] ?? null);
|
||||
}
|
||||
}
|
||||
|
||||
private List<GameExtendedAttribute> GetGameExtendedAttributes<T>(
|
||||
List<T_Game_ChildList> gameChildList,
|
||||
string gameId,
|
||||
int childType,
|
||||
Dictionary<int, T> dictionary) where T : class
|
||||
private List<GameExtendedAttribute> GetGameExtendedAttributes<T>(List<T_Game_ChildList> gameChildList, string gameId, int childType, Dictionary<int, T> dictionary) where T : class
|
||||
{
|
||||
return gameChildList
|
||||
.Where(it => it.GameId == gameId && it.ChildType == childType && (it.ChildId ?? 0) > 0)
|
||||
|
|
@ -217,25 +248,26 @@ namespace CloudGaming.Code.Cache.Special
|
|||
|
||||
public override bool ClearData()
|
||||
{
|
||||
lock (GameEntityCacheLock)
|
||||
{
|
||||
database.KeyDelete(key);
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
_dataList = null;
|
||||
gameInfoDic = null;
|
||||
}
|
||||
|
||||
database.KeyDelete(key);
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
database.KeyDelete(RedisKey);
|
||||
_dataList = null;
|
||||
gameInfoDic = null;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public override void ReloadData()
|
||||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
database.KeyDelete(key);
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
_dataList = null;
|
||||
var x = DataList;
|
||||
}
|
||||
database.KeyDelete(key);
|
||||
database.KeyDelete(RedisKey);
|
||||
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
|
||||
_dataList = null;
|
||||
var x = DataListAsync.Result;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,39 +26,33 @@ namespace CloudGaming.Code.Epg
|
|||
public async Task<List<EpgCategoryDto>> GetHomeInfo()
|
||||
{
|
||||
var listQueryable = GetEpgCategory(EpgEnum.EpgCatIdName.大厅首页).AsQueryable();
|
||||
if (IsChecking)
|
||||
{
|
||||
listQueryable = listQueryable.Where(it => it.ShowStatus == 0 || it.ShowStatus == 2).AsQueryable();
|
||||
}
|
||||
else
|
||||
{
|
||||
listQueryable = listQueryable.Where(it => it.ShowStatus == 0 || it.ShowStatus == 1).AsQueryable();
|
||||
}
|
||||
var list = listQueryable.OrderBy(it => it.OrderId).ToList();
|
||||
int[] showStatus = IsChecking ? [0, 2] : [0, 1];
|
||||
var list = listQueryable.Where(it => showStatus.Contains(it.ShowStatus)).OrderBy(it => it.OrderId).ToList();
|
||||
|
||||
List<EpgCategoryDto> epgCategoryDtos = new List<EpgCategoryDto>();
|
||||
list.ForEach(it =>
|
||||
foreach (var it in list)
|
||||
{
|
||||
var list = new List<EpgInfo>()
|
||||
var epglist = new List<EpgInfo>()
|
||||
{
|
||||
//STEAMCLOUD
|
||||
};
|
||||
var epgList = GetEpgList(it.Id);
|
||||
epgList?.ForEach(item =>
|
||||
foreach (var item in epgList)
|
||||
{
|
||||
//如果首页展示数量小于集合数量,则退出
|
||||
if (it.ShowNumIndex < list.Count)
|
||||
if (it.ShowNumIndex < epglist.Count)
|
||||
{
|
||||
return;
|
||||
break;
|
||||
}
|
||||
var epgInfo = item.ToEpgInfo(Cache.GameEntityCache);
|
||||
var epgInfo = await item.ToEpgInfo(Cache.GameEntityCache);
|
||||
if (epgInfo != null)
|
||||
{
|
||||
list.Add(epgInfo);
|
||||
epglist.Add(epgInfo);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (list.Count > 0)
|
||||
|
||||
if (epglist.Count > 0)
|
||||
{
|
||||
EpgCategoryDto epgCategoryDto = new EpgCategoryDto()
|
||||
{
|
||||
|
|
@ -66,12 +60,13 @@ namespace CloudGaming.Code.Epg
|
|||
CategoryType = it.IdName,
|
||||
IsQuickStartPopUp = it.IsQuickStartPopUp ?? false,
|
||||
ShowNum_Index = it.ShowNumIndex ?? 0,
|
||||
EpgList = list
|
||||
EpgList = epglist
|
||||
};
|
||||
|
||||
epgCategoryDtos.Add(epgCategoryDto);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return epgCategoryDtos;
|
||||
}
|
||||
/// <summary>
|
||||
|
|
|
|||
|
|
@ -20,7 +20,7 @@ namespace CloudGaming.Code.Epg
|
|||
/// <param name="epgCfg"></param>
|
||||
/// <param name="gameEntityCache"></param>
|
||||
/// <returns></returns>
|
||||
public static EpgInfo ToEpgInfo(this T_Epg_Cfg epgCfg, GameEntityCache gameEntityCache)
|
||||
public static async Task<EpgInfo> ToEpgInfo(this T_Epg_Cfg epgCfg, GameEntityCache gameEntityCache)
|
||||
{
|
||||
if (epgCfg.ResType == (int)EpgEnum.EpgResType.游戏 && string.IsNullOrEmpty(epgCfg.ResId))
|
||||
{
|
||||
|
|
@ -41,7 +41,7 @@ namespace CloudGaming.Code.Epg
|
|||
|
||||
if (epgCfg.ResType == (int)EpgEnum.EpgResType.游戏)
|
||||
{
|
||||
var gameInfo = gameEntityCache[epgCfg.ResId];
|
||||
var gameInfo = await gameEntityCache[epgCfg.ResId];
|
||||
if (gameInfo == null)
|
||||
{
|
||||
return null;
|
||||
|
|
|
|||
|
|
@ -24,10 +24,8 @@ namespace CloudGaming.Code.Game
|
|||
/// <returns></returns>
|
||||
public async Task<List<GameExtendedAttribute>> GetGameTypeListAsync()
|
||||
{
|
||||
var gameList = Cache.GameEntityCache?.DataList ?? new List<GameInfo>();
|
||||
var gameTypes = await Task.Run(() =>
|
||||
{
|
||||
return CloudGamingCacheExtend.GetDataEntityCache<T_Game_Types>(this, it => it.IsOnline)?.DataList
|
||||
var gameList = await Cache.GameEntityCache.DataListAsync;
|
||||
var list = CloudGamingCacheExtend.GetDataEntityCache<T_Game_Types>(this, it => it.IsOnline)?.DataList
|
||||
.Where(it => gameList.Any(item => item.GameType?.Any(gameType => gameType.Id == it.TypeId) ?? false))
|
||||
.OrderBy(it => it.OrderId)
|
||||
.Select(it => new GameExtendedAttribute
|
||||
|
|
@ -37,9 +35,9 @@ namespace CloudGaming.Code.Game
|
|||
OrderId = it.OrderId
|
||||
})
|
||||
.ToList();
|
||||
});
|
||||
return list;
|
||||
|
||||
|
||||
return gameTypes;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
@ -49,14 +47,8 @@ namespace CloudGaming.Code.Game
|
|||
/// <returns></returns>
|
||||
public async Task<List<GameListDto>> GetGameListAsync(int typeId)
|
||||
{
|
||||
|
||||
var gameListDto = await Task.Run(() =>
|
||||
{
|
||||
var gameList = Cache.GameEntityCache?.DataList ?? new List<GameInfo>();
|
||||
var x = gameList.Where(it => it.GameType?.Any(item => item.Id == typeId) ?? false).Select(it => new
|
||||
GameListDto(it)).ToList();
|
||||
return x;
|
||||
});
|
||||
var gameList = await Cache.GameEntityCache.DataListAsync;
|
||||
var gameListDto = gameList.Where(it => it.GameType?.Any(item => item.Id == typeId) ?? false).Select(it => new GameListDto(it)).ToList();
|
||||
return gameListDto;
|
||||
|
||||
}
|
||||
|
|
@ -65,13 +57,13 @@ namespace CloudGaming.Code.Game
|
|||
/// </summary>
|
||||
/// <param name="gameId"></param>
|
||||
/// <returns></returns>
|
||||
public GameInfoDto GetGameInfo(string gameId)
|
||||
public async Task<GameInfoDto> GetGameInfo(string gameId)
|
||||
{
|
||||
if (string.IsNullOrEmpty(gameId))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var game = Cache.GameEntityCache[gameId];
|
||||
var game = await Cache.GameEntityCache[gameId];
|
||||
if (game == null)
|
||||
{
|
||||
return null;
|
||||
|
|
@ -85,12 +77,12 @@ namespace CloudGaming.Code.Game
|
|||
/// </summary>
|
||||
/// <param name="gameId"></param>
|
||||
/// <returns></returns>
|
||||
public List<GameListDto> GameRecommendations(string gameId)
|
||||
public async Task<List<GameListDto>> GameRecommendations(string gameId)
|
||||
{
|
||||
List<GameInfo>? gameInfos = null;
|
||||
if (!string.IsNullOrEmpty(gameId))
|
||||
{
|
||||
var game = Cache.GameEntityCache[gameId];
|
||||
var game = await Cache.GameEntityCache[gameId];
|
||||
if (game != null)
|
||||
{
|
||||
var gameTagIds = game.GameTags.Select(it => it.Id);
|
||||
|
|
|
|||
|
|
@ -32,7 +32,7 @@ namespace CloudGaming.Code.MiddlewareExtend
|
|||
{
|
||||
// 检查当前请求是否需要缓存
|
||||
var cacheAttribute = GetCacheAttribute(context);
|
||||
if (cacheAttribute == null)
|
||||
if (cacheAttribute == null || true)
|
||||
{
|
||||
await _next(context);
|
||||
return;
|
||||
|
|
|
|||
|
|
@ -1,11 +1,14 @@
|
|||
using HuanMeng.DotNetCore.CacheHelper.Contract;
|
||||
|
||||
using Microsoft.EntityFrameworkCore.Metadata.Internal;
|
||||
|
||||
using Newtonsoft.Json;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace HuanMeng.DotNetCore.CacheHelper
|
||||
|
|
@ -55,12 +58,8 @@ namespace HuanMeng.DotNetCore.CacheHelper
|
|||
{
|
||||
lock (lockObj)
|
||||
{
|
||||
tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
|
||||
if (tempDataList == null)
|
||||
{
|
||||
tempDataList = GetDataList();
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
||||
}
|
||||
tempDataList = GetDataList();
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
||||
}
|
||||
}
|
||||
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList));
|
||||
|
|
@ -95,4 +94,120 @@ namespace HuanMeng.DotNetCore.CacheHelper
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 异步缓存
|
||||
/// </summary>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
public abstract class CommonDataEntityCacheAsync<T> : ICacheClearData, ICacheReloadData where T : class
|
||||
{
|
||||
|
||||
/// <summary>
|
||||
/// 过期时间
|
||||
/// </summary>
|
||||
protected int cacheTime;
|
||||
|
||||
private readonly SemaphoreSlim _semaphore; // 异步锁
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
/// <param name="semaphore">异步锁new SemaphoreSlim(initialCount: 1, maxCount: 1); </param>
|
||||
/// <param name="cacheTime"></param>
|
||||
protected CommonDataEntityCacheAsync(SemaphoreSlim semaphore, int cacheTime = 36000)
|
||||
{
|
||||
//new SemaphoreSlim(initialCount: 1, maxCount: 1);
|
||||
this._semaphore = semaphore;
|
||||
this.cacheTime = cacheTime;
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
///
|
||||
/// </summary>
|
||||
public abstract string key { get; }
|
||||
|
||||
/// <summary>
|
||||
/// 缓存数据
|
||||
/// </summary>
|
||||
protected List<T>? _dataList;
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 数据
|
||||
/// </summary>
|
||||
public virtual Task<List<T>> DataListAsync
|
||||
{
|
||||
get
|
||||
{
|
||||
// 如果已有缓存数据,直接返回
|
||||
if (_dataList != null)
|
||||
{
|
||||
return Task.FromResult(_dataList);
|
||||
}
|
||||
|
||||
// 尝试从缓存获取
|
||||
var tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
|
||||
if (tempDataList != null)
|
||||
{
|
||||
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList)) ?? new List<T>();
|
||||
return Task.FromResult(_dataList);
|
||||
}
|
||||
return Task.Run(async () =>
|
||||
{
|
||||
// 进行异步加锁,避免多线程竞争
|
||||
await _semaphore.WaitAsync();
|
||||
try
|
||||
{
|
||||
// 重新检查缓存
|
||||
tempDataList = MemoryCacheHelper.GetCache<List<T>>(key);
|
||||
if (tempDataList == null)
|
||||
{
|
||||
tempDataList = await GetDataListAsync(); // 异步获取数据
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
||||
}
|
||||
_dataList = JsonConvert.DeserializeObject<List<T>>(JsonConvert.SerializeObject(tempDataList)) ?? new List<T>();
|
||||
|
||||
return _dataList;
|
||||
}
|
||||
finally
|
||||
{
|
||||
_semaphore.Release(); // 释放锁
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 获取缓存数据
|
||||
/// </summary>
|
||||
public abstract Task<List<T>> GetDataListAsync();
|
||||
|
||||
/// <summary>
|
||||
/// 清除缓存
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
public virtual bool ClearData()
|
||||
{
|
||||
|
||||
MemoryCacheHelper.DelCache(key);
|
||||
_dataList = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 重新加载缓存
|
||||
/// </summary>
|
||||
public virtual void ReloadData()
|
||||
{
|
||||
|
||||
var tempDataList = GetDataListAsync().Result;
|
||||
MemoryCacheHelper.SetCache(key, tempDataList, cacheTime);
|
||||
_dataList = tempDataList;
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
using Microsoft.Extensions.Caching.Memory;
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
|
@ -40,6 +41,18 @@ namespace HuanMeng.DotNetCore.CacheHelper
|
|||
cache.Set(cacheName, val, TimeSpan.FromSeconds(cacheTime));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 设置缓存
|
||||
/// </summary>
|
||||
/// <param name="cacheName"></param>
|
||||
/// <param name="val"></param>
|
||||
/// <param name="cacheTime">单位秒,默认1小时</param>
|
||||
public static void SetCache(string cacheName, object val, TimeSpan timeSpan)
|
||||
{
|
||||
cache.Set(cacheName, val, timeSpan);
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// 删除缓存
|
||||
/// </summary>
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user