2

我正在使用.NET 4.0,所以我无法使用async/await关键字。如何正确设置HttpClient的延续?

在我辛苦地设置任务和继续而不是仅仅调用.Result之后,我得到的所有努力都是一团糟,它在几十个HTTP GET的工作负载上运行速度降低了46%。 (如果我以串行或并行循环的方式将工作负载称为工作负载,我会得到类似的性能下降)

我该做些什么才能看到任何性能优势?

//Slower code 
public UserProfileViewModel GetAsync(Guid id) 
{ 
    UserProfileViewModel obj = null;//Closure 
    Task result = client.GetAsync(id.ToString()).ContinueWith(responseMessage => 
    { 
      Task<string> stringTask = responseMessage.Result 
              .Content.ReadAsStringAsync(); 
      Task continuation = stringTask.ContinueWith(responseBody => 
      { 
       obj = JsonConvert 
        .DeserializeObject<UserProfileViewModel>(responseBody.Result); 
      }); 
      //This is a child task, must wait before returning to parent. 
      continuation.Wait(); 
     }); 
    result.Wait(); 
    return obj; 
} 

//Faster code 
public UserProfileViewModel GetSynchr(Guid id) 
{ 
    //Asych? What's is that? 
    HttpResponseMessage response = client.GetAsync(id.ToString()).Result; 
    string responseBody = response.Content.ReadAsStringAsync().Result; 
    return JsonConvert.DeserializeObject<UserProfileViewModel>(responseBody); 
} 

回答

3

您正在使用“异步”方法,但同步执行所有操作。这当然不会比同步方法同步一切更好。

看看这个:

public Task<UserProfileViewModel> GetAsync(Guid id) 
{ 
    var uri = id.ToString(); 
    return client.GetAsync(uri).ContinueWith(responseTask => 
    { 
     var response = responseTask.Result; 
     return response.Content.ReadAsStringAsync().ContinueWith(jsonTask => 
     { 
      var json = jsonTask.Result; 
      return JsonConvert.DeserializeObject<UserProfileViewModel>(json); 
     }); 
    }).Unwrap(); 
} 

注意如何使用该方法返回一个Task和延续从方法返回。这允许你的方法几乎立即返回,给予调用者对正在运行的工作的处理,无论需要发生什么延续。返回的任务只有完成后才会完成,结果将是您的UserProfileViewModel

Unwrap方法需要Task<Task<UserProfileViewModel>>并将其变成Task<UserProfileViewModel>

+0

你的'Unwrap'方法是一个相当差的实现,特别是考虑到有一个实现烘焙到.NET中,它正确地执行它。 – Servy 2014-09-18 19:07:43

+0

@Servy我错误地认为它只是在.NET 4.5中。我从.NET 4.0(OP要求的版本)中删除了快速和肮脏的实现。 – 2014-09-18 19:09:13

+0

即使是这样,无论如何,你的实现依赖于.NET 4.5方法。 – Servy 2014-09-18 19:10:59