在webapi中正确使用等待异步

时间:2013-08-13 05:39:21

标签: c# asp.net-mvc-4 asp.net-web-api .net-4.5 async-await

我有一个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的调用是在本地缓存的,所以我并没有看到使这个异步化的巨大好处。

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

2 个答案:

答案 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);});