【发布时间】:2014-11-27 07:43:52
【问题描述】:
我在自己创建的 Web API 中有以下操作:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public CartTotalsDTO GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh);
}
对这个 web 服务的调用是通过 Jquery Ajax 调用完成的:
$.ajax({
url: "/api/products/pharmacies/<%# Farmacia.PrimaryKeyId.Value.ToString() %>/page/" + vm.currentPage() + "/" + filter,
type: "GET",
dataType: "json",
success: function (result) {
vm.items([]);
var data = result.Products;
vm.totalUnits(result.TotalUnits);
}
});
我见过一些开发者这样实现之前的操作:
// GET api/<controller>
[HttpGet]
[Route("pharmacies/{pharmacyId}/page/{page}/{filter?}")]
public async Task<CartTotalsDTO> GetProductsWithHistory(Guid pharmacyId, int page, string filter = null ,[FromUri] bool refresh = false)
{
return await Task.Factory.StartNew(() => delegateHelper.GetProductsWithHistory(CustomerContext.Current.GetContactById(pharmacyId), refresh));
}
不过,必须说 GetProductsWithHistory() 是一个相当长的操作。鉴于我的问题和背景,使 webAPI 操作异步对我有什么好处?
【问题讨论】:
-
客户端使用AJAX,已经是异步的了。您不需要将该服务也写为
async Task<T>。请记住,AJAX 在 TPL 存在之前就已经实现了 :) -
您需要了解为什么要实现异步控制器,很多人没有。 IIS 的可用线程数量有限,当所有线程都在使用时,服务器无法处理新请求。使用异步控制器,当进程等待 I/O 完成时,它的线程被释放给服务器用于处理其他请求。
-
您见过哪些开发人员这样做?如果有任何推荐该技术的博客文章或文章,请发布链接。
-
只有当您的进程从顶部(包括 Web 应用程序本身和您的控制器)到任何超出您的进程的可等待活动(包括计时器延迟、文件 I/O、数据库访问和它发出的 Web 请求)。在这种情况下,您的委托助手需要返回
Task<CartTotalsDTO>的GetProductsWithHistoryAsync()。如果您也打算将控制器的调用迁移为异步,那么编写异步控制器可能会有好处;然后在迁移其余部分时开始从异步部分中受益。 -
如果您正在执行的进程正在关闭并访问数据库,那么您的 Web 线程只是在等待它返回并持有该线程。如果你已经达到了最大线程数并且另一个请求进来了,它必须等待。为什么要这样做?相反,您希望从您的控制器中释放该线程,以便另一个请求可以使用它,并且仅在您来自数据库的原始请求返回时才占用另一个 Web 线程。 msdn.microsoft.com/en-us/magazine/dn802603.aspx
标签: c# jquery ajax asp.net-web-api async-await