ASP.NET MVC3如何等待异步回调并返回结果

时间:2013-11-29 06:44:18

标签: c# asynchronous callback

背景

我正在使用缓存预热功能,通过在请求之前在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);
                        });
        }

1 个答案:

答案 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));
}