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