微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

ASP.NET:当控制器在快速运行的任务上退出时,异步执行对较慢运行的任务的回调

如何解决ASP.NET:当控制器在快速运行的任务上退出时,异步执行对较慢运行的任务的回调

我有一个 ASP.NET 控制器,它在内部调用 API 和缓存以获取答案,并从完成的第一个任务中返回答案。一般来说,API比缓存慢很多,缓存在50ms内返回,而API在第95个百分位2秒内返回。

要求:

  1. 如果可用,立即从缓存中返回答案。否则等待 API 并返回可用/空响应(视情况而定)。
  2. 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 举报,一经查实,本站将立刻删除。