背景
我正在使用缓存预热功能,通过在请求之前在Cache中预加载对象来提高ASP.NET MVC Web的性能。
我使用Azure角色内缓存,在更新/删除/添加缓存等时提供了AddItemLevelCallback功能。我已经共享了下面的代码逻辑。
问题:
下面的代码片段中显示的NotifyOnceCacheIsUpdated上的AddItemLevelCallback不会立即被调用,直到添加/更新项目为止。请求需要等待。但问题是AddItemLevelCallback是异步的,DAL上的KickOffWarmUpCache可能会在添加/更新实际项目之前返回。
处理这种情况的优雅方法是什么,其中KickOffWarmUpCache仅在触发AddItemLevelCallback之后才将结果返回给调用者。
技术:MVC3,.NET Framework 4.5
代码示例:
CONTROLLER
public void WarmUpCache(string id)
{
var userInfo = BLL.KickOffWarmUpCache(string id);
}
BLL
public UserInfo KickOffWarmUpCache(string id)
{
return DAL.KickOffWarmUpCache(string id)
}
DAL
public UserInfo KickOffWarmUpCache(string id)
{
UserInfo userInfo = new UserInfo();
//If Status = Progress
if (cache.Get(id).Status == "Progress")
{
NotifyOnceCacheIsUpdated(id,(result)=>
{
userInfo=result.userInfo;
});
}else{
userInfo=Cache.Get(id);
}
//This needs to wait for until callback is triggered and userInfo is populated
return userInfo;
}
UTIL
public void NotifyOnceCacheIsUpdated(string cacheKey, Action<T> callback)
{
DataCacheOperations allCacheOperations = DataCacheOperations.ReplaceItem | DataCacheOperations.AddItem ;
_ndItemLvlAllOps = cache.AddItemLevelCallback(cacheKey, allCacheOperations,
(CacheName, cacheRegion, cacheKey, itemVersion, OperationId, nd) =>
{
cachedData = cache.Get(cacheKey);
callback(cachedData);
});
}
答案 0 :(得分:1)
public Task<UserInfo> KickOffWarmUpCache(string id)
{
//If Status = Progress
if (cache.Get(id).Status == "Progress")
{
var ret = new TaskCompletionSource<UserInfo>();
NotifyOnceCacheIsUpdated(id,(result)=>
{
//complete the task.
ret.SetResult(result.userInfo);
});
//return a Task...which the SetResult will complete.
return ret.Task;
}
//Return a result synchronously
return Task.FromResult(Cache.Get(id));
}