我有一个WebApi,对于每个传入的请求,调用2个单独的Web服务,执行一些后期处理并返回结果。
第一个webservice调用在本地缓存1小时,其中的数据确定对第二个webservice的查询。每个传入请求都会调用第二个Web服务。在发出第二个请求之后,每个结果都使用业务逻辑处理并返回到客户端响应。
对第二个webservice的调用不能是异步的,因为它使用的是不允许await关键字的第三方dll。我所做的是将第二个webservice调用和后处理包装到一个异步函数中,该函数从控制器调用。
// /api/controller/news?key=a&state=b
public async Task<HttpResponseMessage> GetNews(string key, string state)
{
// call to first webservice if not in cache
if (JsonConfig != null && JsonConfig.Configuration.NewsQuery.ContainsKey(key))
{
var results = await SearchProxyProvider.Search(filters.All, filters.Any, filters.None, filters.Sort, 100, 0, true, state, true);
int totalCount = results.TotalCount;
return Request.CreateResponse(HttpStatusCode.OK, results);
}
}
// Helper class method
public async Task<ItemCollection<Item>> Search(List<FieldValuePair> allFilters, List<FieldValuePair> anyFilters, List<FieldValuePair> noneFilters, SortedFieldDictionary sortBy, int pageSize = 100, int pageNumber = 0, bool exact = true, string stateFilter = null, bool getAllResults = true)
{
// call to 2nd api
search = SomeApi.Search(allFilters, anyFilters, noneFilters, pageSize, pageNumber, exact,
sortBy, null, WebApiConstant.Settings.CustomFields, true);
// post processing on search results
return search;
}
因为对第一个webservice的调用是在本地缓存的,所以我并没有看到使这个异步化的巨大好处。
我只是想看看这种方法是完全错误还是正确。
答案 0 :(得分:8)
第一个webservice调用在本地缓存1小时,其中的数据决定了对第二个webservice的查询。
您可以使用AsyncLazy<T>
(例如from my blog)执行一些操作并将其缓存。这为您的请求提供了一种(异步)等待刷新的方法,当您需要刷新数据时,无论同时请求的数量是多少,您都不会多次点击Service1。
对第二个webservice的调用不能是异步的,因为它使用的第三方dll不允许使用await关键字。
那真是太糟糕了。靠它们来修理它。 :)
我所做的是将第二个webservice调用和后处理包装到一个异步函数中,该函数从控制器调用。
没有意义。编译器会警告您,“异步”方法实际上是同步的。
如果它是同步的,那么只需同步调用它。在服务器端,没有必要将它包装在Task.Run
或类似的东西中。
我周一在slides available from an "Async on the Server" talk给了一些ThatConference,你可能会觉得有帮助。 (他们有关于如何处理异步请求的动画以及为什么“伪异步”方法在服务器端没有帮助。)
答案 1 :(得分:0)
要使功能搜索真正异步,可以将对SomeApi.Search的调用包装到单独的任务中,然后等待。还要考虑将第一个函数中的代码包装到一个任务中,使用负载估计缓存验证也可能是一个瓶颈。
// call to 2nd api
var search = await Task.Factory.StartNew(()=> {return Some Api.Search(allFilters, anyFilters, noneFilters, pageSize, pageNumber, exact,
sortBy, null, WebApiConstant.Settings.CustomFields, true);});