使用带有超时的httpClient进行异步/等待调用

时间:2015-03-17 14:49:48

标签: c# timeout async-await dotnet-httpclient

基于另一个问题的答案: HttpClient async requests not completing for large batch sent out in a loop

我正在使用扩展方法并应用他们建议的逻辑使用HttpClient类的超时,并避免挂起或没有响应。

 public static Task<T> WithTimeout<T>(this Task<T> task, TimeSpan timeout)
 {
      var delay = task.ContinueWith(t => t.Result
          , new CancellationTokenSource(timeout).Token);
      return Task.WhenAny(task, delay).Unwrap();
 }

因此,像这样调用HttpClient应该可以防止任何“任务变坏”永无止境:

  Task<HttpResponseMessage> _response = httpClient.PostAsJsonAsync<Object>(Target, new Object()).WithTimeout<HttpResponseMessage>(httpClient.Timeout);

现在,在应用它时,使用填充了循环的Task数组,我希望所有任务并行运行并以指定的超时值结束。 只是为了显示一个示例,我将设置超时时间为400毫秒,但是在任务后约20秒后,在Tasks.WhenAll(任务)行之后的下一行。

public async Task<JObject> GetResponse(JObject request, TimeSpan timeout)
    {   
            Timespan timeout = Timespan.FromMilliseconds(400);  
            HttpClient httpClient = new HttpClient();
            HttpResponseMessage response = await httpClient.PostAsJsonAsync<string>(string.Format("{0}api/GetResponse", endpoint), localRequest.ToString()).WithTimeout<HttpResponseMessage>(timeout);
            return await response.Content.ReadAsAsync<JObject>().WithTimeout<JObject>(timeout); 
    }

调用异步方法:

        Task<JObject>[] tasks = new Task<JObject>[totalResultCounter];

        foreach (JObject request in anArray)
        {
            tasks[counter] = GetResponse(request);
        }

        await Task.WhenAll(tasks);
        MyNextMethod();

预计500毫秒和下一行完成的任务是否会被击中?为什么到达MyNextMethod线需要大约20秒?也许我在PostAsJsonAsync / ReadAsAsync调用中设置超时时做错了什么?

超时扩展方法可以很好地隔离。

当我使用关键字await时,它似乎等待完成,但是没有使用定义的超时:

HttpResponseMessage response =等待httpClient.PostAsJsonAsync(string.Format(“{0} api / GetSupplierResponse”,endpoint),localRequest.ToString())。WithTimeout(timeout);

如果我将其更改为:

 Task<HttpResponseMessage> response = httpClient.PostAsJsonAsync<string>(string.Format("{0}api/GetResponse", endpoint), localRequest.ToString()).WithTimeout<HttpResponseMessage>(timeout);

很快。

但是我如何得到结果呢?我需要使用等待ReadAsAsync方法:

 JObject result = await response.Content.ReadAsAsync<JObject>().WithTimeout<JObject>(timeout);

一旦我使用它,需要花费大量时间,20秒才能完成我的200个项目的循环。

PostAsJsonAsync和ReadAsAsync应作为独立任务处理,不考虑httpClient中指定的超时?或者这些方法的使用需要超过500毫秒,这就是为什么在使用循环时需要花费很多的时间?

任何帮助/概念澄清都将受到赞赏。

0 个答案:

没有答案