如何解决ASP.NET:当控制器在快速运行的任务上退出时,异步执行对较慢运行的任务的回调
我有一个 ASP.NET 控制器,它在内部调用 API 和缓存以获取答案,并从完成的第一个任务中返回答案。一般来说,API比缓存慢很多,缓存在50ms内返回,而API在第95个百分位2秒内返回。
要求:
- 如果可用,立即从缓存中返回答案。否则等待 API 并返回可用/空响应(视情况而定)。
- API 调用完成后,我们会使用新答案更新缓存(如果有)。
问题: 如何在不阻塞控制器的情况下等待 API 调用并在后台线程中写入缓存?
当前流量:
Task<string>[] getDataTasks = new Task<string>[]
{
getDataFromAPI(),getDataFromCache()
};
var finishedTaskIndex = Task.WaitAny(getDataTasks);
var response = getDataTasks[finishedTaskIndex].Result;
if (finishedTaskIndex == 1 && string.IsNullOrEmpty(response))
{
response = await getDataTasks[0];
writetoCacheTask(response); //fire and forget,this is non-blocking
}
**//Problem :- How to await for response from API and write to cache in a non-blocking manner** THIS DOES NOT WORK
Task.Run(async () =>
{
var apiResponse = await getDataTasks[0];
writetoCacheTask(apiResponse);
});
return response;
在上面,即使我使用一个新线程来等待独立于主线程的api调用,它也不起作用。
不起作用 尝试在任务上使用 ContinueWith 并带有 TaskContinuationoptions = ExecuteSynchronously 的回调,因为这会在调用任务的同一线程上继续。但我可能理解错了。
Task.Run(async () =>
{
return await getDataTasks[0];
}).ContinueWith(this.CallBack,TaskContinuationoptions.ExecuteSynchronously);
有效:使用委托处理程序
// private members of controller
private delegate string DelegateHandler();
private string getDataFromAPisync()
{
return getDataFromAPI().GetAwaiter().GetResults();
}
private string getDataFromCacheSync()
{
return getDataFromCache().GetAwaiter().GetResults();
}
private void CallBack(IAsyncResult ar)
{
var apiResponse = apiInvoker.EndInvoke(ar);
writetoCacheTask(apiResponse);
}
// In controller
var apiInvoker = new DelegateHandler(this.getDataFromAPisync)
var cacheInvoker = new DelegateHandler(this.getDataFromCacheSync)
IAsyncResult apiResults = apiInvoker.BeginInvoke(this.CallBack,null);
IAsyncResult cacheResults = cacheInvoker.BeginInvoke(null,null);
var handles = new WaitHandle[]
{
apiResults.AsyncWaitHandle,cacheResults.AsyncWaitHandle
}
WaitHandle.WaitAny(handles);
if (cacheResults.IsCompleted)
{
return cacheInvoker.EndInvoke(ar);
}
return apiInvoker.EndInvoke(ar);
当我使用委托处理程序时,它看起来像用于进行 api 调用的后台线程,也用于处理回调,并且只有在回调完成后它才会被终止。
如何使用任务库做同样的事情?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。