C# ASP.NET MVC3如何等待异步回调并返回结果
背景: 我正在开发缓存预热功能,通过在请求对象之前将其预加载到缓存中来提高ASP.NET MVC Web上的性能 我在角色缓存中使用Azure,它在更新/删除/添加缓存时提供AddItemLevelCallback函数。我在下面分享了代码逻辑 问题: 在添加/更新项之前,不会立即调用下面的代码段中显示的NotifyOnCeCacheIsUpdate上的AddItemLevelCallback。请求将需要等待。但问题是AddItemLevelCallback是异步的,DAL上的KickOffWarmUpCache可能会在添加/更新实际项之前返回 如果KickOffWarmUpCache仅在触发AddItemLevelCallback后才将结果返回给调用者,那么处理这种情况的优雅方式是什么呢 技术:MVC3、.NETFramework 4.5 代码示例: 控制器C# ASP.NET MVC3如何等待异步回调并返回结果,c#,asynchronous,callback,C#,Asynchronous,Callback,背景: 我正在开发缓存预热功能,通过在请求对象之前将其预加载到缓存中来提高ASP.NET MVC Web上的性能 我在角色缓存中使用Azure,它在更新/删除/添加缓存时提供AddItemLevelCallback函数。我在下面分享了代码逻辑 问题: 在添加/更新项之前,不会立即调用下面的代码段中显示的NotifyOnCeCacheIsUpdate上的AddItemLevelCallback。请求将需要等待。但问题是AddItemLevelCallback是异步的,DAL上的KickOffWar
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));
}