8

我有一个 WebApi,对于每个传入的请求,调用 2 个单独的 Web 服务,执行一些后处理并返回结果。

第一个 webservice 调用在本地缓存 1 小时,其中的数据决定了对第二个 webservice 的查询。对每个传入请求调用第二个 Web 服务。在发出第二个请求后,每个结果都使用业务逻辑进行处理并返回给客户端响应。

对第二个 Web 服务的调用不能是异步的,因为它使用了不允许 await 关键字的第 3 方 dll。我所做的是将第二个 web 服务调用和后处理包装到一个异步函数中,该函数从控制器调用。

// /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;
        }

因为对第一个 web 服务的调用是在本地缓存的,所以我并没有真正看到使这个异步的巨大好处。

我只是想看看这种方法是完全错误的还是正确的。

4

2 回答 2

8

第一个 webservice 调用在本地缓存 1 小时,其中的数据决定了对第二个 webservice 的查询。

AsyncLazy<T>您可以使用(例如,从我的博客)做一些技巧并缓存它。这为您的请求提供了一种(异步)等待刷新的方法,并且当您需要刷新数据时,无论同时请求的数量如何,您都不会多次点击 Service1。

对第二个 Web 服务的调用不能是异步的,因为它使用了不允许 await 关键字的第 3 方 dll。

真可惜。一定要依靠他们来解决它。:)

我所做的是将第二个 web 服务调用和后处理包装到一个异步函数中,该函数是从控制器调用的。

这没有任何意义。编译器会警告您,您的“异步”方法实际上是同步的。

如果它是同步的,那么只需同步调用它。在服务器端,将其包装Task.Run或类似的东西是没有意义的。

我周一在ThatConference上发表的“服务器上的异步”演讲中提供了一些幻灯片,您可能会发现这些幻灯片很有帮助。(他们有关于如何处理异步请求以及为什么“假异步”方法对服务器端没有帮助的动画)。

于 2013-08-14T23:05:58.040 回答
0

为了使函数 Search 真正异步调用 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);});
于 2013-08-14T14:59:08.893 回答