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

C# ASP.NET MVC3如何等待异步回调并返回结果,c#,asynchronous,callback,C#,Asynchronous,Callback,背景: 我正在开发缓存预热功能,通过在请求对象之前将其预加载到缓存中来提高ASP.NET MVC Web上的性能 我在角色缓存中使用Azure,它在更新/删除/添加缓存时提供AddItemLevelCallback函数。我在下面分享了代码逻辑 问题: 在添加/更新项之前,不会立即调用下面的代码段中显示的NotifyOnCeCacheIsUpdate上的AddItemLevelCallback。请求将需要等待。但问题是AddItemLevelCallback是异步的,DAL上的KickOffWar

背景:

我正在开发缓存预热功能,通过在请求对象之前将其预加载到缓存中来提高ASP.NET MVC Web上的性能

我在角色缓存中使用Azure,它在更新/删除/添加缓存时提供AddItemLevelCallback函数。我在下面分享了代码逻辑

问题:

在添加/更新项之前,不会立即调用下面的代码段中显示的NotifyOnCeCacheIsUpdate上的AddItemLevelCallback。请求将需要等待。但问题是AddItemLevelCallback是异步的,DAL上的KickOffWarmUpCache可能会在添加/更新实际项之前返回

如果KickOffWarmUpCache仅在触发AddItemLevelCallback后才将结果返回给调用者,那么处理这种情况的优雅方式是什么呢

技术:MVC3、.NETFramework 4.5

代码示例:

控制器

 public void WarmUpCache(string id)
 {
    var userInfo = BLL.KickOffWarmUpCache(string id);
 }
BLL

达尔

利用率

public void NotifyOnceCacheIsUpdated(字符串缓存键,操作回调)
{
DataCacheOperations allCacheOperations=DataCacheOperations.ReplaceItem | DataCacheOperations.AddItem;
_ndItemLvlAllOps=cache.AddItemLevelCallback(cacheKey,allCacheOperations,
(CacheName、cacheRegion、cacheKey、itemVersion、OperationId、nd)=>
{
cachedData=cache.Get(cacheKey);
回调(cachedData);
});
}
公共任务KickOffWarmUpCache(字符串id)
{
//如果状态=进度
if(cache.Get(id.Status==“Progress”)
{
var ret=new TaskCompletionSource();
NotifyOnceCacheIsUpdated(id,(结果)=>
{
//完成任务。
ret.SetResult(result.userInfo);
});
//返回SetResult将完成的任务。
返回返回返回任务;
}
//同步返回结果
返回Task.FromResult(Cache.Get(id));
}

您是否考虑过只使用
任务
异步
?是的,但不会解决给定的问题,即等待并返回回调函数给出的结果…等待并返回结果是
任务
异步
的全部思想。或者您的问题是您当前的功能不在TPL友好签名中?如果是这种情况,您应该在
TaskCompletionSource
中总结逻辑。谢谢@aron,您是否能够澄清return ret.Task与Task.FromResult(new UserInfo())之间的区别。稍后是否返回空对象?我还添加了else{userInfo=cache.Get(id);}。
Task.FromResult
用于返回结果已完成的任务。通常,在可以同步生成结果时使用它。而
TaskCompletionSource.Task
返回一个尚未完成的
Task
,可以通过另一个线程使用
TaskCompletionSource.SetResult
完成。
public UserInfo KickOffWarmUpCache(string id)
{
    return DAL.KickOffWarmUpCache(string id)
}
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;
}
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);
                        });
        }
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));
}